shikoan’s memo

プログラミング初心者のチラ裏

ぷろぐらみんぐ帳

numpy.ufunc.reduceatの意味

100 Numpy Exercisesの78問目より。この関数意味わからなかった。ちなみにこんな問題。ブロック単位での和を計算することを想定している。

78.Consider a 16x16 array, how to get the block-sum (block size is 4x4)? (★★★)

# Author: Robert Kern

Z = np.ones(16,16)
k = 4
S = np.add.reduceat(np.add.reduceat(Z, np.arange(0, Z.shape[0], k), axis=0),
                                       np.arange(0, Z.shape[1], k), axis=1)

試してみる

リファレンスからどんな挙動をするのか試してみる。

numpy.ufunc.reduceat — NumPy v1.14 Manual

>>> import numpy as np
>>> x = np.arange(16).reshape(4,4)
>>> x
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])

とりあえず第2引数のベクトルの要素を1つにしてadd.reduceしてみる(ufuncのところは関数が入るのでaddでもmultiplyでも何でも良い)。

>>> np.add.reduceat(x,[0])
array([[24, 28, 32, 36]], dtype=int32)
>>> np.add.reduceat(x,[1])
array([[24, 27, 30, 33]], dtype=int32)
>>> np.add.reduceat(x,[2])
array([[20, 22, 24, 26]], dtype=int32)
>>> np.add.reduceat(x,[3])
array([[12, 13, 14, 15]], dtype=int32)

なるほど、1番上から、

  • [0]の場合:4行全ての列で集計した合計
  • [1]の場合:2行目~4行目の列で集計した合計
  • [2]の場合:3行目~4行目の列で集計した合計
  • [3]の場合:4行目の列で集計した合計=4行目の値

やっていることはわかった。要素を2つに増やしてみる。以下、形式的にn行目の列単位の集計した合計をrownと書く。[2]の場合はrow3+row4、[3]の場合はrow4となる。

>>> np.add.reduceat(x,[0,1])
array([[ 0,  1,  2,  3],
       [24, 27, 30, 33]], dtype=int32)
>>> np.add.reduceat(x,[0,2])
array([[ 4,  6,  8, 10],
       [20, 22, 24, 26]], dtype=int32)
>>> np.add.reduceat(x,[0,3])
array([[12, 15, 18, 21],
       [12, 13, 14, 15]], dtype=int32)
>>> np.add.reduceat(x,[1,3])
array([[12, 14, 16, 18],
       [12, 13, 14, 15]], dtype=int32)
>>> np.add.reduceat(x,[2,3])
array([[ 8,  9, 10, 11],
       [12, 13, 14, 15]], dtype=int32)
>>> np.add.reduceat(x,[1,2])
array([[ 4,  5,  6,  7],
       [20, 22, 24, 26]], dtype=int32)

まとめてみる。

  • [0,1]→[row1] [row2+row3+row4]
  • [0,2]→[row1+row2] [row3+row4]
  • [0,3]→[row1+row2+row3] [row4]
  • [1,3]→[row2+row3][row4]
  • [2,3]→[row3][row4]
  • [1,2]→[row2][row3+row4]

だいたい傾向が読めてきたのではないだろうか?リファレンスを読むと次のようなルールがある。

For i in range(len(indices)), reduceat computes ufunc.reduce(a[indices[i]:indices[i+1]]), which becomes the i-th generalized “row” parallel to axis in the final result (i.e., in a 2-D array, for example, if axis = 0, it becomes the i-th row, but if axis = 1, it becomes the i-th column). There are three exceptions to this:

  • when i = len(indices) - 1 (so for the last index), indices[i+1] = a.shape[axis].
  • if indices[i] >= indices[i + 1], the i-th generalized “row” is simply a[indices[i]].
  • if indices[i] >= len(a) or indices[i] < 0, an error is raised.

もともとreduceという関数を元にしていて、それの区間選択できるバージョンらしい。reduceを実行してみると、

>>> np.add.reduce(x,axis=0)
array([24, 28, 32, 36])

reduceのaxisは列で集計するか行で集計するかというオプションで、reduceatにも存在する。つまりreduceの場合は、reduceatにおける[row1+row2+row3+row4]と同等の結果を返した。

じゃあ区間選択はどうやっているのかというと、2要素の場合を見るにこういうルーチンだろう。こう書けばプログラムに馴染みがある人は「ああ、なるほど」となるはずだ。

for i in range(len(indices)):
    if i == len(indices)-1:
        j = len(indices)
    else:
        j = indices[i+1]
    result = 0
    for p in range(i, j):
        result += p+1行目の列単位で集計した合計(=row[p+1])
    yield result

ただしこれは不完全で、indices[i+1]<indices[i]の場合は関数適用するのではなく、単純にrow[indices[i]]を返すという例外がある。他の例外として範囲外のインデックスを与えるとエラーを返すとかあるが、当たり前なので省略。

この例外を使った例はこちら。何を返し、どういう計算が行われているかわかりますか?

>>> np.add.reduceat(x,[0,2,0])
array([[ 4,  6,  8, 10],
       [ 8,  9, 10, 11],
       [24, 28, 32, 36]], dtype=int32)

結果の1行目は[row1+row2]、2行目[row3]、3行目は[row1+row2+row3+row4]。indices[1]>indices[2]なので例外が適用され、2行目は[row3+row4]ではなく[row3]なのがポイント。さらに3行目でインデックスが0に戻り、row1~row4までの合計を計算している。

一周するとインデックスが戻るのはreduceat(x,[0,2,1,3])のように実行するとより詳しく確認できる。

>>> np.add.reduceat(x,[0,2,1,3])
array([[ 4,  6,  8, 10],
       [ 8,  9, 10, 11],
       [12, 14, 16, 18],
       [12, 13, 14, 15]], dtype=int32)

1行目はrange(0,2)なので、[row1+row2]。2行目は例外適用で[row3]。3行目は一周してrange(1,3)で[row2+row3]、4行目はrange(3,4)なので[row4]が返されている。なので、一周するというよりかは、2行目の例外が一周のときの挙動でその例外適用=インデックスを0に戻すなのかもしれない(もうちょっと詳しく確認する必要はあり)。

かなりとっつきにくい関数ではあったが、理解を深めることはできた。確かに、冒頭の100 Numpy Exercisesに出ているように、ブロック単位での合計を計算するのに便利な関数ではあると思う。

numpy.bincountのweightの意味

100 Numpy Exercisesの56問目で解いていたときにふと湧いた疑問。こんな問題。

56.How to accumulate elements of a vector (X) to an array (F) based on an index list (I)? (★★★)

# Author: Alan G Isaac

X = [1,2,3,4,5,6]
I = [1,3,9,3,4,1]
F = np.bincount(I,X)
print(F)

解説

第2引数を指定しない場合はわかりやすい。0以上の整数が登場した回数を表す。

>>> import numpy as np
>>> x = np.random.randint(0,10,10)
>>> x
array([8, 5, 0, 4, 1, 2, 7, 0, 3, 1])
>>> np.bincount(x)
array([2, 2, 1, 1, 1, 1, 0, 1, 1], dtype=int64)

結果は、0が登場した回数、1が登場した回数……と続く。とてもわかりやすい(randintが整数の乱数発生関数なので、結果は実行するたびに変わるのに注意)。

第2引数はweight(重み付け)の引数である。これが何について重み付けしているのかわからずにハマった。weightのベクトルを用意する。

>>> w = np.linspace(0.1,1,10)
>>> w
array([ 0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9,  1. ])
>>> np.bincount(x,w)
array([ 1.1,  1.5,  0.6,  0.9,  0.4,  0.2,  0. ,  0.7,  0.1])

0は0.1で重み付け、1は0.2で重み付けしているのかなと思ったらそうではない。なんだろう?と数十分試していてようやくわかった。このweightは登場する値に対する重み付けではなく、サンプルに対する重み付けなのだ

この場合、

  • xの1番目の8のサンプルは0.1としてカウントする
  • xの2番目の5のサンプルは0.2としてカウントする
  • : : :
  • xの10番目の1のサンプルは1としてカウントする

これをやっていたのだ。確かにこれで計算すると辻褄が合う。

リファレンスをよく見ると載っていた。

weights is specified the input array is weighted by it, i.e. if a value n is found at position i, out[n] += weight[i] instead of out[n] += 1.

numpy.bincount — NumPy v1.14 Manual

つまりデフォルトでは重み付けのパラメーターを全て1として指定した場合と同等ですよと。なるほど、これでスッキリした。

フランスのホスティング会社iKoulaで専用サーバーを丸々1台借りてみた

日本国内のサーバー会社だと、専用サーバーって個人で簡単に借りられる金額ではないんですよね。

例:さくらサーバーより
・さくらスタンダードシリーズ
Xeon E3-1230 v5 4C/8T 3.4GHz 最大3.8GHz
メモリ 標準8GB 最大64GB
ストレージ 標準2台1組 最大2台
これで初期費用86400円、月額9720円

VPSもそうだが、専用サーバーも海外だと結構安いところがある。スペック次第だが、月額20ドルぐらいから借りられるところは存在する。これはLowEndTalk(海外のホスティング会社比較のコミュニティサイトで、企業側もプロモーションコードなどの宣伝をこちらで行っていることがある)で見つけた案件で、iKoulaというフランスのホスティング会社。

例:iKoula dedicated serverより、低価格帯のもの
Intel Green G3900 1CPU(2C/2T) @ 2.8GHz, 8GB DDR4, 2TB SATA3
初期費用€60、月額€19.99 → 初期費用なし、プロモコードで最初の1ヶ月または3ヶ月間は€9.99
Xeon E3-1220v5 1CPU(4C/4T) @ 3GHz, 8GB DDR4, 1TB SATA, GeForce GT 710 1GB
初期費用€60、月額€29.99 → 初期費用なし、プロモコードで最初の1ヶ月または3ヶ月間は€14.99
Xeon E3-1230v5、1CPU(4C/8T) @ 3.4GHz, 8GB DDR4, 1TB SATA, GeForce GT 710 1TB
初期費用€60、月額€39.99 → 初期費用なし、プロモコードで最初の1ヶ月または3ヶ月間は€24.99

3番目はさくらのスタンダードシリーズとほぼ同じ構成で、申し訳ばかりにグラフィックボードがついてくる(申し訳ばかりなのでスペックは期待しないほうがいい)。GeForceがついているので簡単なディープラーニングならできるかもしれない。通常価格で比較してもさくらボリすぎでしょ常識的に考えて

フランスの会社ということで、セットアップ完了時のメールがフランス語で飛んでくるが、英語のサポートも受け付けている。英語でメール送れば親切に返してくれるし、申し込みの手続きは英語でできる(たまに途中でフランス語のページにリダイレクトされる)。支払い方法はPayPal対応。公式ページに日本語のページがあるが、翻訳が怪しすぎるので素直に英語で行ったほうが吉。自分はフランス語はボンジュールぐらいしかわからない。

2番目のE3-1220v5のプランで3ヶ月借りてみた。現在3ヶ月間使用料が半額になるプロモーションコードを出していて、それを適用して月額€15で使用できた。料金はPayPalの場合は一括前払い。

支払いして2時間程度で使用可能になった。一般的なVPSだと一瞬だが、専用サーバー丸々1台なのでセットアップにちょっと時間かかるのかもしれない。OSの再インストールも少し時間かかって、一般的なVPSだと1~2分だが、1時間はかかった。イメージ的にはPCのOS再インストールをしているのと同じなので、それぐらいかかって然るべきであろう。

ロケーションがフランス(ブローニュ=ビヤンクールというパリ郊外の都市にある会社なので、ロケーションはおそらくパリあたり?)なので、ping値は250ms程度。ヨーロッパにつなぐとイギリスだろうがフランスだろうがこれぐらいの時間はかかるので仕方ない。日本からは、海底ケーブルで直に繋がっているアメリカ西海岸のロケーションだと100msや100ms切りぐらいで接続できる。tracertを見てると、日本から太平洋を海底ケーブルを通って、アメリカ西海岸に上陸して(ここに100msぐらい)サンフランシスコ、デンバークリーブランドオールバニ、ボストンと五大湖に沿って北米大陸を突っ切って(ここに80msぐらい)、ボストンの先から大西洋の海底ケーブルを通ってロンドンに上陸して(ここに70ms)、あとはそのままパリへという感じらしい。インターネットの壮大な旅を体感できる。

CPUの性能はどれぐらいかというと、CPU Benchmarkというサイトが参考になる。

PassMark Software - CPU Benchmark Charts

これによると、

Intel Xeon E3-1220 v5 @ 3.00GHz
AverageCPUMark : 7670
https://www.cpubenchmark.net/cpu.php?cpu=Intel+Xeon+E3-1220+v5+%40+3.00GHz&id=2692

ちなみに自分が使っているPCのCPUはCore i5-4440なので、

Intel Core i5-4440 @ 3.10GHz
AverageCPUMark : 6483
https://www.cpubenchmark.net/cpu.php?cpu=Intel+Core+i5-4440+%40+3.10GHz&id=2017

若干E3-1220のほうが良いかなという感。ベンチマーク用に某仮想通貨を掘ってみたら以下のようなハッシュレートだった(レートはマイニングプールに表示されている4時間の平均レート)。

Core i5-4440 (WindowsPCでのバックグラウンド作業なしのCPU100%のフルバースト):2.64KH/s
・E3-1220v5(Ubuntu16.04、専用サーバーなのでCPULimit等はなし):2.52KH/s

なので、ベンチマークスコアに反して若干i5のほうに軍配が上がった。自分の知識不足かもしれないが、Windows用のクライアントのほうがCPUごとのチューニングが多いので、プログラムそのもののハッシュ効率がいいのかもしれない。

別にマイニングでも機械学習でも、外から見たらCPUやGPUをフルバーストしていることには変わらないので、VPSのようなCPU共用環境だとおそらく嫌われる可能性が高い(特に前者はToSで明確に禁止しているところも多いが、"dedicated"な専用VPSや専用サーバーを同時に提供している会社では専用環境に限りこの禁止を除外しているところも同時に多い)。共用環境での他の使用者によるロード増加は「noisy neighbor」と言われたりするが、この問題がトラブルを気にする必要がないのが専用サーバーの大きな利点である。
この問題は長くなるので軽くにおさえるが、CPU共用の場合「ここまでの使用率ならいいですよ」という線引が明示されていない場合、使用中のサーバーを停止する権利は100%運営会社側にあり、そのさじ加減で止められたり生き残ったりするというのが最大のリスクである。ToS(Terms of service)やAUP(Acceptable Use Policy)の禁止事項には触れていないのに、自分も何の予告もなく止められたことがある。計算資源の確保だったら、サーバーではなく一周回ってリアルにPCを買うのがかなり賢い選択であると思う。noisy neighbor問題ではないが、価格面での計算資源の確保に苦労しているのは、やねうら王の開発者のブログでも書かれているので暇な方はぜひ読んで欲しい。

マシン1000台きぼんぬ | やねうら王 公式サイト

UnixBench

かなり脱線したが、UnixBenchも実行してみた。今気づいたけどv5じゃなくてv6と新しいバージョンになっていた。素晴らしい。

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: 117467HD012176: GNU/Linux
   OS: GNU/Linux -- 4.4.0-71-generic -- #92-Ubuntu SMP Fri Mar 24 12:59:01 UTC 2                                                                                                                                                             017
   Machine: x86_64 (x86_64)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   CPU 0: Intel(R) Xeon(R) CPU E3-1220 v6 @ 3.00GHz (5999.7 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT,                                                                                                                                                              SYSCALL/SYSRET, Intel virtualization
   CPU 1: Intel(R) Xeon(R) CPU E3-1220 v6 @ 3.00GHz (5999.7 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT,                                                                                                                                                              SYSCALL/SYSRET, Intel virtualization
   CPU 2: Intel(R) Xeon(R) CPU E3-1220 v6 @ 3.00GHz (5999.7 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT,                                                                                                                                                              SYSCALL/SYSRET, Intel virtualization
   CPU 3: Intel(R) Xeon(R) CPU E3-1220 v6 @ 3.00GHz (5999.7 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT,                                                                                                                                                              SYSCALL/SYSRET, Intel virtualization
   20:26:44 up 27 min,  1 user,  load average: 0.00, 0.02, 0.00; runlevel 5

------------------------------------------------------------------------
Benchmark Run: Tue Mar 27 2018 20:26:44 - 20:54:50
4 CPUs in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       35116147.8 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     3929.6 MWIPS (9.2 s, 7 samples)
Execl Throughput                               3371.2 lps   (29.9 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks       1244958.9 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          329891.9 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       2978350.3 KBps  (30.0 s, 2 samples)
Pipe Throughput                             2254015.4 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 135085.9 lps   (10.0 s, 7 samples)
Process Creation                              13504.2 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   9598.0 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                   4244.9 lpm   (60.0 s, 2 samples)
System Call Overhead                        3968283.5 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   35116147.8   3009.1
Double-Precision Whetstone                       55.0       3929.6    714.5
Execl Throughput                                 43.0       3371.2    784.0
File Copy 1024 bufsize 2000 maxblocks          3960.0    1244958.9   3143.8
File Copy 256 bufsize 500 maxblocks            1655.0     329891.9   1993.3
File Copy 4096 bufsize 8000 maxblocks          5800.0    2978350.3   5135.1
Pipe Throughput                               12440.0    2254015.4   1811.9
Pipe-based Context Switching                   4000.0     135085.9    337.7
Process Creation                                126.0      13504.2   1071.8
Shell Scripts (1 concurrent)                     42.4       9598.0   2263.7
Shell Scripts (8 concurrent)                      6.0       4244.9   7074.9
System Call Overhead                          15000.0    3968283.5   2645.5
                                                                   ========
System Benchmarks Index Score                                        1840.1

------------------------------------------------------------------------
Benchmark Run: Tue Mar 27 2018 20:54:50 - 21:22:56
4 CPUs in system; running 4 parallel copies of tests

Dhrystone 2 using register variables      140517202.8 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                    15720.0 MWIPS (9.2 s, 7 samples)
Execl Throughput                              23912.1 lps   (29.9 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks       1363581.8 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          354108.1 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       4144599.8 KBps  (30.0 s, 2 samples)
Pipe Throughput                             8908439.7 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                1525448.8 lps   (10.0 s, 7 samples)
Process Creation                              65358.4 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                  45262.5 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                   5485.2 lpm   (60.0 s, 2 samples)
System Call Overhead                        8196732.1 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0  140517202.8  12040.9
Double-Precision Whetstone                       55.0      15720.0   2858.2
Execl Throughput                                 43.0      23912.1   5560.9
File Copy 1024 bufsize 2000 maxblocks          3960.0    1363581.8   3443.4
File Copy 256 bufsize 500 maxblocks            1655.0     354108.1   2139.6
File Copy 4096 bufsize 8000 maxblocks          5800.0    4144599.8   7145.9
Pipe Throughput                               12440.0    8908439.7   7161.1
Pipe-based Context Switching                   4000.0    1525448.8   3813.6
Process Creation                                126.0      65358.4   5187.2
Shell Scripts (1 concurrent)                     42.4      45262.5  10675.1
Shell Scripts (8 concurrent)                      6.0       5485.2   9142.0
System Call Overhead                          15000.0    8196732.1   5464.5
                                                                   ========
System Benchmarks Index Score                                        5497.0

ファイルコピーはHDDを選択。特に断りもなくSATAと書かれていたが、SSDの場合はオプション料金が必要だったのでHDD。ちなみにsmartctlで型番を調べてみたらTOSHIBA HDWD110だった。方法は以下参照。

LinuxでHDD/SSDなどの型番を調べる方法 - Qiita

Cpuinfoの確認

cat /proc/cpuinfoで確認。これが4つ

processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 158
model name      : Intel(R) Xeon(R) CPU E3-1220 v6 @ 3.00GHz
stepping        : 9
microcode       : 0x5e
cpu MHz         : 800.000
cache size      : 8192 KB
physical id     : 0
siblings        : 4
core id         : 0
cpu cores       : 4
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 22
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 dtherm arat pln pts hwp hwp_notify hwp_act_window hwp_epp
bugs            :
bogomips        : 5998.70
clflush size    : 64
cache_alignment : 64
address sizes   : 39 bits physical, 48 bits virtual
power management:

これで「俺はフランスの物理サーバーを丸々1台借りたことがあるぞ!!」とドヤれるわけである。やったね!

VPSを使い始めたときの初期設定(Ubuntu編)

自分用メモ。

CentOSに飽きたのでUbuntuを使ってみた。基本的には同じ。インストールオプションでUbuntu17.04も選べたが、2018年1月にEodOfLifeを迎えているので、apt installを行うときにちょっと手間取る。後発バージョンを使うか、よりサポート期間の長い16.04を使う。

www.ubuntu.com

以下、Ubuntu16.04での例。TeraTermSSH接続する。

1.ユーザーの追加

rootパスワードを変更しておく。

passwd

rootは作業に適さないので、一般ユーザーを追加する

adduser username

useraddでも追加されるが、adduserのほうがパスワードの設定など包括的にできて良い(気がする)。Full NameとかRoom Numberは全部そのまま初期設定でエンター。

追加したユーザーにsudo権限を付与。

gpasswd -a username sudo

sudoを実行するたびにパスワード入力するのは面倒くさいので、それほど気にしない環境なら以下のように変更(ちゃんとした環境ではやらないように

visudo
# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) NOPASSWD: ALL

Ctrl+O→そのままエンターで上書き保存(エディタはnanoになる)。Ctrl+Xで終了。

2.SSHの設定

SSHのポート設定とルートログインを無効にする。SSHサーバーがインストールされていなければ、「apt install openssh-server」でインストールする。

vi /etc/ssh/sshd_config

Port22は有名すぎてDoS攻撃の対象になるだけなので適当な数字に変更する。編集はiキーを押すと編集開始、ESCキーで編集終了になる。

# What ports, IPs and protocols we listen for
Port XXXX #ここを22から変更

ルートログインも無効にする。

# Authentication:
LoginGraceTime 120
PermitRootLogin no #ここをyesからnoに変更
StrictModes yes

ESCで編集モードを抜けて、「:wq」で設定を保存する。パスワードログインはよほど環境に自信があれば切ってもいいが、再起動後など何かの拍子で公開鍵ログインができなくなることがあるので、自信がなければ残しておいたほうが無難。

SSHサーバーを再起動。

systemctl restart ssh

3.アップデートをかける

apt update
apt upgrade -y

数分かかる

4.ファイアーウォールの設定

再起動後もiptablesの内容が維持されるようにiptables-persistentをインストール(ここだけUbuntuが特殊)

apt install iptables-persistent

これが出てこない場合は3のapt updateやapt upgradeを忘れているはず。以下、設定。ほぼこのサイトを継承。

iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP #データを持たないパケットを破棄
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP #SYNflood攻撃と思われるものを破棄
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP #ステルススキャンと思われるものを破棄
iptables -A INPUT -i lo -j ACCEPT #localhostからの通信とpingを許可
iptables -A INPUT -p icmp -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport XXXX -j ACCEPT #SSH用のポートを許可(2で設定したポート番号を入力)
iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT #HTTP(80)を許可
iptables -A INPUT -p tcp -m tcp --dport 10000 -j ACCEPT #Webmin(10000)を許可
iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT #確立済みの接続を許可
iptables -P INPUT DROP #許可した通信以外のサーバーから受信するパケットを拒否
iptables -P OUTPUT ACCEPT #サーバーから送信するパケットの許可

コピペする前にXXXXを指定したSSHポートで置き換えたか注意。これをやらないと次回ログインできなくなる(多分)。変更を保存。

/etc/init.d/netfilter-persistent save

5.公開鍵認証

TeraTermで公開鍵は作成済みのものとする。一旦ログアウトし、一般ユーザーで再ログイン(この場合ポート番号は変更済みのものを入力すること)。

ログインできたら「id_rsa.pub」をドラッグアンドドロップし、「~/」作業ディレクトリに「SCP」で転送。次のコマンドを実行。

mkdir .ssh
chmod 700 .ssh
cat id_rsa.pub > .ssh/authorized_keys
chmod 600 .ssh/authorized_keys
rm -f id_rsa.pub

ログアウトして、公開鍵認証でもログインできるか確認。

できたら終わり。お疲れ様でした。

参考資料

VPSを新規に借りた直後にすべきセキュリティ設定 | Time4VPSのまとめ

さくらのVPSでUbuntu16.04を建てた - Qiita

Ubuntuでiptablesを再起動後にも保持する方法 - Qiita

サクッとUbuntuサーバーの初期設定をする - Qiita

オプション1.Python3.6のインストール

追記:2018/5 公式サイトの方法だとget-pip.py実行時にエラーが出ることがあります。PPAを変更すると暫定的に解決できます。

qiita.com

デフォルトでインストールされているPython3.5だと一部のライブラリ(psutil)が上手く行かなかったので、Python3.6をインストールしたら上手くいった。インストール方法はこちらを参照。

www.python.jp

CentOS7+Python3.xで日本語を内容に含むファイル出力をしたときにUnicodeEncodeErrorがでたときの対策

環境:CentOS7、Python3.6

Windows環境では発生しなかったのにLinux環境で実行したら発生した。

test.py

with open("hoge.txt", "w") as fp:
    fp.write(u"あああああいいいいうううう日本語")
Traceback (most recent call last):
  File "test.py", line 2, in <module>
    fp.write(u"\u3042\u3042\u3042\u3042\u3042\u3044\u3044\u3044\u3044\u3046\u3046\u3046\u3046\u65e5\u672c\u8a9e")
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-15: ordinal not in range(128)

【原因】OSのデフォルトエンコードANSIだった。公式ドキュメントにあった。open()関数のドキュメントより。

2. 組み込み関数 — Python 3.6.4 ドキュメント

encoding はファイルのエンコードやデコードに使われる text encoding の名前です。このオプションはテキストモードでのみ使用してください。デフォルトエンコーディングはプラットフォーム依存 (locale.getpreferredencoding() が返すもの) ですが、Pythonでサポートされているエンコーディングはどれでも使えます。詳しくは codecs モジュール内のサポートしているエンコーディングのリストを参照してください。

locale.getpreferredencoding() を確認してみる。

[*****]$ python3.6
Python 3.6.4 (default, Dec 19 2017, 14:48:12)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale
>>> locale.getpreferredencoding()
'ANSI_X3.4-1968'

つまり、openの際にエンコードを"utf-8"と指定してやる必要がある。

with open("hoge.txt", "w", encoding="utf-8") as fp:
    fp.write(u"あああああいいいいうううう日本語")

無事、保存することができた。(別にu””はつけてもつけなくてもOK)

型の違う配列やTupleをjoinで文字列結合するときの注意

大丈夫だろうと甘く見ていたら怒られたのでメモ

Pythonは型にルーズなので、配列やTupleの中に文字列と数字が混在していても特に問題なし。例えば次のようなTupleは許容される。

a = (1,"a",2)

ところが文字列結合すると途端にうるさくなる。例えばこれですらダメ。

a = (1,"a",2)
s = ""
for i in a:
    s += i
print(s)
#    s += i
#TypeError: must be str, not int

str(i)とキャストが必要。joinで結合するときはもっと気づきにくいかもしれない。こうする必要がある。

a = (1,"a",2)
s = "".join(str(x) for x in a)
print(s)

ハマるときはハマるかもしれない。

月額2.5ドルから使える素敵なクラウドVPS「Vultr」の良いポイント

日本でもそこそこ有名になりつつある、海外VPSの『Vultr』を使ってみた。

いろいろ解説しているサイトがあるので(例えばこのへん↓)端折るけど、自分の独断と偏見でポイントを紹介。

www.pr1sm.com

qiita.com

1. 何と言っても月額2.5ドルのインスタンス

これが一本抜けている。安いのは素晴らしい。月額2.5ドルのインスタンス(サーバー)で、20GBのSSD、1コアCPU(バーチャル)、512MBメモリ、500GBの転送量がついてくる。しかもこれ、時間計算。本当の計算方法は時間割の0.004ドル/hで、これの天井金額が月額2.5ドル。なので、月の途中で契約してもまるまる月額分請求されることはないし、使わないときはストップしておけばその分カウントが減るはず1

ただし、超過分の転送量は従量課金になるらしい。FAQから。

At what rate is overage bandwidth billed? Bandwidth utilization in excess of instance allocation is charged at $0.01 per GB in North American and Western European locations. Due to higher regional costs, Singapore and Tokyo (Japan) overage is priced at $0.025 per GB and Sydney (Australia) overage is priced at $0.05 per GB.

Vultr.com Frequently Asked Questions - Vultr.com

Vultrの北米と西ヨーロッパのリージョンは$0.01/GB、シンガポールと日本は$0.025/GB、オーストラリアはなんと$0.05/GBもする。Amazon EC2の場合は東京リージョンのアウトで$0.140/GBも取っていて無料枠も雀の涙なので、だいぶ良心的かもしれない。ただし、転送量の計算方法が違って、Vultrはインとアウトの多いとこを取るし、転送量も時間あたりの無料枠超過分(500GBだったら500/672=0.74GB/h)を超過したのに対して課金するシステム(なので瞬間的に転送量が増えるようなケースには弱い)。転送量からちょっと離れるが、Vultrの場合はよくあるVPSレンタルサーバー同様、アップスケーリングはできるがダウンスケーリングはできない(というか非推奨?)。ここが注意がいる。

そもそも、Vultrの場合クレジットをチャージしておいてそこから引き落とす(後述)というシステムが使えるので、クラウド破産のリスクはだいぶ減る。ただ転送量関係がややこしいので、超過したら503出したり、低速になったりするようなシステムはなさそう。なので、WordPress置いたりするのにはちょっと不向きかもしれない(転送量が読みづらいから)。転送量が読みやすい自分専用のサーバーなんかにはとてもうってつけ

2. 月額2.5ドルのロケーション

2018年3月頭現在、2.5ドルの使えるロケーションはアメリカのマイアミとニューヨーク。東京とかいう極東の僻地にはそんな便利なインスタンスないし、北米より東京のほうがハードウェアのベンチマークで優れているかというとそんなことはない。試しに月額5ドルの東京のインスタンスを使ってみたら、5ドル出すほどよくはなかったのでさっさとDestroyしてしまった。日本から接続するならping面のメリットはあるが(東京が10msぐらいで、北米が160~170ms)、そこまでpingの0.1秒を気にするようなことはしないから特に問題ない。「ジャップの都が何だ、世界のニューヨークを使ってるぞ」でいい気分になってもいいし、マイアミで南国気分になってもいい。

3.大事なこと:2.5ドルのインスタンスはまで2つしか持てない

これあまり大きく書いていないのだが(クソ長いTosにはしっかり書かれている2)、2.5ドルのインスタンスは1人2個までしか持てない。3個以上持とうとすると、

Unable to place order: You have reached the maximum number of active instances (2) with our sandbox plan. Please choose a different plan.

と怒られる。2.5ドルのプランはテスト用のsandboxという位置づけらしい。まあこんだけコスパいいインスタンスを大量に持たれても困るよね。

4.クレジットのプリペイド方式

海外のVPSではたまに見かけるがここが良い。Suicaのようなイメージがわかりやすい。プリペイドが日本のお家芸だと思ったら大間違え。一旦10ドル、25ドルとクレジットを追加しておいて、そこから仕様分に応じて引かれるシステム。クレジットが足りなくなった場合は直ちにSuspendされるようではないようだが、その間も加算されるのかは読んでもよくわからなかった。参考。

discuss.vultr.com

支払いはPaypal経由が一番やりやすい。PaypalにはVプリカも紐付けられるので、そこらの日本のサーバーよりも支払いが簡単だったりする(ちょっと割高になるけど)。調べてみたら、国産のConoHaもようやくプリペイドカードを出したらしい(アニメ柄で可愛い)。でもこれで国内初だというのは業界全般的に遅れている感はある(ちらっと調べて出てきたAWSプリペイド集金代行とか完全に食い物にしている感じしかしない)。

5.コンソールがとてもわかりやすい

コンソールが今まで触った海外VPSの中で一番充実している。よくあるテンプレートタイプではないので、コンソールにJavaが必須だったりするようなことはない。そしてCPUの仕様状況もわかりやすい。ただ、シリアルコンソールがぱっと見たところないので、パスワード認証切ってログインできなくなると詰むかもしれない。

いかんせん全部英語なのだが、今更英語だからちょっと…というのも(法律関係の面倒で専門的なやり取りをするなら別だが)Linux使っててだから何なの?という感はあるので、英語に特に抵抗感のない人は知識の分だけお得にいけるということでありがたくつかわせてもらおう。英語がいやでいやで仕方がないという人はさくらの初期費用でも払って、どうぞ。

6.UnixBenchの結果

北米のマイアミの2.5ドルインスタンス

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: vultr.guest: GNU/Linux
   OS: GNU/Linux -- 3.10.0-693.17.1.el7.x86_64 -- #1 SMP Thu Jan 25 20:13:58 UTC 2018
   Machine: x86_64 (x86_64)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   CPU 0: Virtual CPU a7769a6388d5 (4788.9 bogomips)
          x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET
   21:42:16 up 8 min,  1 user,  load average: 0.11, 0.13, 0.06; runlevel 3

------------------------------------------------------------------------
Benchmark Run: Sun Mar 04 2018 21:42:16 - 22:10:07
1 CPU in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       28097460.5 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     4415.6 MWIPS (8.0 s, 7 samples)
Execl Throughput                               3264.0 lps   (30.0 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        632044.1 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          177198.2 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       1442202.1 KBps  (30.0 s, 2 samples)
Pipe Throughput                              966982.3 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 145121.8 lps   (10.0 s, 7 samples)
Process Creation                               9365.6 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   4592.8 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                    620.5 lpm   (60.0 s, 2 samples)
System Call Overhead                         935729.4 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   28097460.5   2407.7
Double-Precision Whetstone                       55.0       4415.6    802.8
Execl Throughput                                 43.0       3264.0    759.1
File Copy 1024 bufsize 2000 maxblocks          3960.0     632044.1   1596.1
File Copy 256 bufsize 500 maxblocks            1655.0     177198.2   1070.7
File Copy 4096 bufsize 8000 maxblocks          5800.0    1442202.1   2486.6
Pipe Throughput                               12440.0     966982.3    777.3
Pipe-based Context Switching                   4000.0     145121.8    362.8
Process Creation                                126.0       9365.6    743.3
Shell Scripts (1 concurrent)                     42.4       4592.8   1083.2
Shell Scripts (8 concurrent)                      6.0        620.5   1034.2
System Call Overhead                          15000.0     935729.4    623.8
                                                                   ========
System Benchmarks Index Score                                         992.5

ファイルコピーがむちゃくちゃ強い。

ユーザー登録してツイッター連携してツイートすると、3ドル分のクレジットがもらえた。あとネトゲでよくある友達招待キャンペーン的なのがあるので、このポストがおもしろかったと思った類まれな人は、下のリンクから登録して30日以上使って10ドル以上チャージするとありがたく射精する。

www.vultr.com

今使っているサーバーの契約が一区切りついたら一旦ここに集約させようかなと思っている。


  1. 厳密にはServer Stopすれば課金が止まるかというとそうでもないらしい。本当に課金を止めたければ「Server Destroy」をすべき。

  2. 16.5 SANDBOX PLAN Vultr offers a 512MB VC2 sandbox plan for testing out our platform. This plan is limited to two instances per account. https://www.vultr.com/legal/tos/