wgetでsegmentation faultが出たときの対症療法

wgetで2.4GBほどある大きなファイルを取得しようとしたとき、以下のようにsegmentation fault (core dumped)が出ました。

$ wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda_10.1.243_418.87.00_linux.run 

(略)
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 2572375299 (2.4G) [application/octet-stream]
`cuda_10.1.243_418.87.00_linux.run' に保存中

cuda_10.1.243_418.87.00_linux.run                   94%[==========================================================================================================>      ]   2.27G  --.-KB/s    残り1m 49s zsh: segmentation fault (core dumped)  wget 

今回の場合、wget--continueフラグを使ってファイルを取得を途中からやり直すことで、無事完走することができました。

$ wget --continue http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda_10.1.243_418.87.00_linux.run 

(略)
HTTP による接続要求を送信しました、応答を待っています... 206 Partial Content
長さ: 2572375299 (2.4G), 129407427 (123M) 残っています [application/octet-stream]
`cuda_10.1.243_418.87.00_linux.run' に保存中

cuda_10.1.243_418.87.00_linux.run                  100%[+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=====>]   2.40G   786KB/s    時間 1m 52s

2019-10-27 19:29:53 (1.11 MB/s) - `cuda_10.1.243_418.87.00_linux.run' へ保存完了 [2572375299/2572375299]

flake8を使いこなす

Pythonのコード改善のためのツール5つを試してみた - minus9d's diary の中で個人的にもっともよさそうだと感じたflake8について、使い方を詳しく調べました。

インストール

$ pip install flake8

バージョンとプラグインの確認

$ flake8 --version

すると、flake8のバージョンと、インストール済のflake8のプラグインの一覧が出てきます。以下に例を示します。

$ flake8 --version
2.6.2 (pycodestyle: 2.0.0, mccabe: 0.5.3, pyflakes: 1.2.3) CPython 3.6.4 on Windows

これはflake8のプラグインを何も入れていない状態での表示例です。ここで表示されるpycodestyle, mccabe, pyflakesが、flake8が初めから備える基本の3点セットです。pycodestypeは「PEP8のスタイル」を、mccabeは「複雑度」を、pyflakesは「エラー解析」をチェックしてくれるものです。

もしあなたが過去にflake8のプラグインをインストールしているとすると表示量が増えます。例えば以前にflake8のプラグインhacking, flake8-import-order, flake8-docstringを以下のコマンド

$ pip install hacking
$ pip install flake8-import-order
$ pip install flake8-docstrings

でインストールしていたとすると、--versionで表示されるのは以下のようになります。

$ flake8 --version
2.6.2 (pycodestyle: 2.0.0, mccabe: 0.5.3, ProxyChecker: 0.0.1, hacking.core: 0.0.1, pyflakes: 1.2.3, import-order: 0.18, flake8-docstrings: 1.3.0, pydocstyle: 2.1.1) CPython 3.6.4 on Windows

以下ではプラグインは何も入れていないものとして話を進めます。

Pythonコードの解析

コードの解析方法は2つあります。1つ目は、以下のように特定のファイルを指定する方法。

$ flake8 sample.py

2つ目は、ディレクトリを指定する方法。

$ flake8 /path/to/dir

コードの解析例

以下のPython 3コードをsample.pyという名前で保存して

import time
import sys
import fractions

def func1(varA,varB):
    '''return sum of a and b'''
    varC = 42
    return (varA + varB)


print(func1(fractions.Fraction(1, 2), fractions.Fraction(1, 3)))
3 + 5
sys.exit(0)

$ flake8 sample.pyでコード解析した結果は以下になります。

sample.py:1:1: F401 'time' imported but unused
sample.py:5:1: E302 expected 2 blank lines, found 1
sample.py:5:15: E231 missing whitespace after ','
sample.py:7:5: F841 local variable 'varC' is assigned to but never used

読み方は、"ファイルパス":行番号":"列番号":"コード":エラー内容 です。 コードの詳細は Warning / Error codes — flake8 2.6.0 documentation を参照してください。

表示の詳細化

--show-sourceオプションを付けると、ソースコードの該当部分もあわせて表示してくれます。

$ flake8 --show-source sample.py
sample.py:1:1: F401 'time' imported but unused
import time
^
sample.py:5:1: E302 expected 2 blank lines, found 1
def func1(varA,varB):
^
sample.py:5:15: E231 missing whitespace after ','
def func1(varA,varB):
              ^
sample.py:7:5: F841 local variable 'varC' is assigned to but never used
    varC = 42
    ^

さらに--show-pep8オプションを付けると、PEP8のルールを表示してくれます。いちいちメッセージの意味を調べる必要がなくて便利です。

$ flake8 --show-source --show-pep8 sample.py
sample.py:1:1: F401 'time' imported but unused
import time
^
sample.py:5:1: E302 expected 2 blank lines, found 1
def func1(varA,varB):
^
    Separate top-level function and class definitions with two blank lines.

    Method definitions inside a class are separated by a single blank line.

    Extra blank lines may be used (sparingly) to separate groups of related
    functions.  Blank lines may be omitted between a bunch of related
    one-liners (e.g. a set of dummy implementations).

    Use blank lines in functions, sparingly, to indicate logical sections.

    Okay: def a():\n    pass\n\n\ndef b():\n    pass
    Okay: def a():\n    pass\n\n\nasync def b():\n    pass
    Okay: def a():\n    pass\n\n\n# Foo\n# Bar\n\ndef b():\n    pass
    Okay: default = 1\nfoo = 1
    Okay: classify = 1\nfoo = 1

    E301: class Foo:\n    b = 0\n    def bar():\n        pass
    E302: def a():\n    pass\n\ndef b(n):\n    pass
    E302: def a():\n    pass\n\nasync def b(n):\n    pass
    E303: def a():\n    pass\n\n\n\ndef b(n):\n    pass
    E303: def a():\n\n\n\n    pass
    E304: @decorator\n\ndef a():\n    pass
    E305: def a():\n    pass\na()
    E306: def a():\n    def b():\n        pass\n    def c():\n        pass
sample.py:5:15: E231 missing whitespace after ','
def func1(varA,varB):
              ^
    Each comma, semicolon or colon should be followed by whitespace.

    Okay: [a, b]
    Okay: (3,)
    Okay: a[1:4]
    Okay: a[:4]
    Okay: a[1:]
    Okay: a[1:4:2]
    E231: ['a','b']
    E231: foo(bar,baz)
    E231: [{'a':'b'}]
sample.py:7:5: F841 local variable 'varC' is assigned to but never used
    varC = 42
    ^
    Indicates that a variable has been explicitly assigned to but not actually
    used.

79文字制限の緩和

PEP8で決められている1行79文字制限が厳しすぎると感じる場合は--max-line-lengthオプションで制限を緩和できます。

$ flake8 --max-line-length=100 sample.py

自分が修正したコードだけをチェック

既存コードを修正してコミットするとき、既存部分のスタイル違反はいったん見て見ぬふりをして、自分が修正した部分だけにflake8でチェックをかけたいことがあります。そのときに使えるのが--diffオプションです。git diffの結果を以下のようにパイプで受けます。

$ git diff sample.py | flake8 --diff

複雑度のチェック

--max-complexity N (Nは整数)をつけると、コードの複雑度(具体的にはサイクロマチック数)が閾値Nを超えている場合に、警告を出せるようになります。使い方の例は以下です。

$ flake8 --max-complexity 12 sample.py

解析除外

flake8による解析を行いたくないファイルには、

# flake8: noqa

という行を追加します。

flake8による解析を行いたくない行には、行末に# noqaを付けます。noqaとはno quality assuranceの略だそうです。

noqaを無視して解析をかけるには--disable-noqaオプションを使います。

ルールのカスタマイズ

特定のルールを無視したいときは--ignoreを使います。例えば以下のようにするとE1, E23, or W503で始まるルールを無視できます。

$ flake8 --ignore=E1,E23,W503 sample.py

逆に、特定のルールだけを有効にしたいときは--selectを使います。例えば以下のようにするとEで始まるルールだけが有効になります。

$ flake8 --select=E sample.py

自動修正は不可能

指摘点を自動修正する機能はflake8にはないようです。autopep8, black, yapfなどのツールを使ってください。(参考:formatting - How do I autoformat some Python code to be correctly formatted? - Stack Overflow

参考URL

Ubuntu 18.04の設定メモ

Ubuntu 18.04をクリーンインストールしようとしてはまる - minus9d's diary の続き。日本語 Remixを使わずにUbuntu 18.04をインストールした場合における設定メモです。

基本設定

Caps Lockキーを潰してCtrlキーとして使う

GUIで行うために

$ sudo apt install gnome-tweak-tool

したあと、

$ gnome-tweaks

でツールを起動し、「キーボードとマウス」→「追加のレイアウトオプション」→「Ctrl Position」→「Caps LockをCtrlとして使う」。

「CtrlとCaps Lockを入れ替える」というオプションも存在しているのだけれど、これを使うとShiftとCtrlの同時押しをうまく扱えないようなのでおすすめしません。

日本語入力

第520回 Ubuntu 18.04 LTSの日本語入力:Ubuntu Weekly Recipe|gihyo.jp … 技術評論社に従う。「⁠設定」の「地域と言語」を開いて「入力ソース」のところにある「+」をクリックし、「⁠日本語 (Mozc)」を追加する必要があるのがポイント。これは気付くのが困難。

画面ロックの時間

デフォルトだと、画面が暗くなるのと同じ時間、すなわち5分で画面ロックされます。これは短すぎるので、画面がロックされるのが早すぎます - Ubuntu 18.04 LTS デスクトップガイド改に従いロック時間を長くします。具体的には、 「設定」→「プライバシー」→「画面ロック」→「画面オフ後にロックするまでの時間」を1時間に変更。

homeのディレクトリ名をカタカナから英語へ

デフォルトだと「デスクトップ」「ダウンロード」などカタカナ表記なのが嫌なので、以下のコマンドで英語に変更します( 参考

  • $ LANG=C xdg-user-dirs-gtk-update
  • "Don't ask me this again"にチェックし、"Update Names"をクリック

電源ボタンを押すとサスペンドするようにする

「設定」→「電源管理」→「電源ボタンを押したときの動作」を「サスペンド」に変更。

追加インストール

インストールされてるパッケージの更新

以下のコマンドで、すでにインストールされてるパッケージを最新版に更新。

$ sudo apt update
$ sudo apt upgrade

apt-getで追加インストール

いつも使うツールをインストール。

$ sudo apt install cmake emacs git lv nkf screen zsh

手動で追加インストール

CUDA Toolkitのインストール (その1)

CUDA Toolkitのインストール方法を調べるとあれこれ方法があって悩みます。今回は公式の方法でインストールします。

まず、上記の1.から2.までに記述された前提条件を自分のシステムが満たしているかをチェックし、指示通りコマンドを打ちます。私の場合は結果的には何もしなくてよいようでした。

次に、CUDA Toolkit 10.2 Download | NVIDIA Developerから、"Linux" -> "x86_64" -> "Ubuntu" -> "18.04" -> "deb(local)" とクリックします。すると、すぐ下に、

$ wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin
$ sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600
$ wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-ubuntu1804-10-1-local-10.1.243-418.87.00_1.0-1_amd64.deb
$ sudo dpkg -i cuda-repo-ubuntu1804-10-1-local-10.1.243-418.87.00_1.0-1_amd64.deb
$ sudo apt-key add /var/cuda-repo-10-1-local-10.1.243-418.87.00/7fa2af80.pub
$ sudo apt-get update
$ sudo apt-get -y install cuda

というコマンド列が表示されるので、これをそのままコンソールで実行します。先程記したURLの3.6の方法と微妙に異なるのが悩ましいのですが、私はこのコマンド列を信じました。

再起動した後、$ nvcc --versionすると以下が表示されました。

$ nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2019 NVIDIA Corporation
Built on Sun_Jul_28_19:07:16_PDT_2019
Cuda compilation tools, release 10.1, V10.1.243

$ nvidia-smiとすると以下が表示されました。

$ nvidia-smi
Mon Nov  4 11:44:47 2019       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.87.00    Driver Version: 418.87.00    CUDA Version: 10.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 1070    On   | 00000000:01:00.0  On |                  N/A |
|  0%   41C    P8     9W / 151W |    438MiB /  8116MiB |      1%      Default |
+-------------------------------+----------------------+----------------------+

(略)

インストール成功のようです。

CUDAのサンプルを取得するには、CUDA Samples :: CUDA Toolkit Documentationにあるように、

$ cuda-install-samples-10.1.sh <target_path>

とします。

CUDA Toolkitのインストール (その2)

CUDA Toolkitを入れる他の方法として、 nvidia - How do I Install CUDA on Ubuntu 18.04? - Ask Ubuntu もあるようです。すなわち、

$ sudo add-apt-repository ppa:graphics-drivers/ppa
$ sudo apt update
$ sudo ubuntu-drivers autoinstall

したあと、再起動し、さらに

$ sudo apt install nvidia-cuda-toolkit gcc-6

します。この結果、nvccやnvidia-smiが/usr/bin/nvcc以下に入りました。

nvcc --versionの結果は以下です。

nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2017 NVIDIA Corporation
Built on Fri_Nov__3_21:07:56_CDT_2017
Cuda compilation tools, release 9.1, V9.1.85

nvidia-smiの結果の一部は以下です。

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 435.21       Driver Version: 435.21       CUDA Version: 10.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 1070    Off  | 00000000:01:00.0  On |                  N/A |
|  0%   43C    P8     8W / 151W |    445MiB /  8116MiB |      1%      Default |
+-------------------------------+----------------------+----------------------+

それぞれで表示されるversionが一致していません。Different CUDA versions shown by nvcc and NVIDIA-smi - Stack Overflowをもし私が正しく理解しているとすると、nvidia-smiで表示される10.1は、nvidiaのdriverがサポートするCUDAのバージョンで、nvcc --versionで表示される9.1は、CUDAのランタイムのバージョンのようです。

CUDAのバージョンをどのように変更できるかはよく分かりません。

追加設定

デフォルトシェルをzshに変更

zshがインストールされていることを確かめたあと、以下のコマンドを打つ( 参考 )

chsh -s $(which zsh)

Ubuntu 18.04をクリーンインストールしようとしてはまる

Ubuntu 18.04をSSDクリーンインストールしようとして盛大にはまりました。以下はそのメモです。

現象

まず以下の手順でUbuntuインストーラUSBメモリを作成しました。

上記インストーラUSBメモリを使ってUbuntu 18.04をインストールしようとすると以下のエラーが出てインストールに失敗しました。

GRUB installation failed

The ‘grub-efi-amd64-signed’ package failed to install into /target/. Without the GRUB boot loader, the installed system will not boot.

試行錯誤

以下のいろいろを試しましたが、どれ一つとしてうまくいきませんでした。

解決策

結局、Ubuntu本家 Ubuntu 18.04.3 LTS (Bionic Beaver) から、UbuntuのDVDイメージubuntu-18.04.3-desktop-amd64.iso をダウンロードし、インストーラーを再作成すると解決しました。いまいち何が悪かったのか自分にはわかりません。

C++のmultisetの使い方

競技プログラミングC++のmultisetをたまに使うことがありますが、毎回使い方を忘れているのでメモしておきます。

(2021-09-05追記: 計算量に誤りがあったので修正)

multisetとは

multisetは、集合を扱うデータ構造です。setと異なり、同じ値の要素を複数持つことができます。#include <set>すれば使えます。さっそく例を示します。

#include <iostream>
#include <set>

void print_multiset(std::multiset<int>& ms) {
    for (auto val: ms) {
        std::cout << val << ", ";
    }
    std::cout << std::endl;
}

int main(void)
{
    std::multiset<int> ms;
    ms.insert(7);
    ms.insert(5);
    ms.insert(2);
    ms.insert(7);
    ms.insert(5);

    print_multiset(ms);
    return 0;
}

とすると、

2, 5, 5, 7, 7,

が表示されます。つまり、変数msに、5つの値が順序付きで登録されていることがわかります。以下では、このように変数msを生成したとしてmultisetの使用例を説明します。

素数を調べる

例えばmsの中に値5を持つ要素が何個含まれているかを調べるには、以下のようにします。

ms.count(5);  // 2と表示される

ただしこれの実行には、全要素数をN、ms中の値5の要素数をMとしてO(log N + M)の時間がかかる (参考 ) ので要注意です。msの全要素が5であるような最悪の場合、M=NなのでO(N)かかってしまうことになります。したがって、値の有無を調べるためだけにcount()メソッドを使ってはいけません。値の有無を調べるにはfind()を使いましょう。find()であれば計算量は O(log N) です。 (参考)

if (ms.find(5) == ms.end()) {
    // 5が存在しない
} else {
    // 5が存在する
}

ある値をもつ要素を全部消す

例えばmsから値5を持つ要素を 全部 消すには、以下のようにします。

ms.erase(5);

ms.erase()は何個の要素を消したかも返すので、もし

auto n = ms.erase(5);

とすると、nには2が入ります。

ms.erase(42);などと存在しない値を消そうとしてもエラーにはなりません。

ある値をもつ要素を1つ消す

例えばmsから値5を持つ要素を 1つだけ 消すには、面倒ですがイテレータを介する必要があります。

ms.erase(ms.find(5));

とすると、msの持つ要素は2, 5, 7, 7となり、5が1個だけ消えます。

msの中にない要素を消そうとするときには要注意です。 もし

ms.erase(ms.find(42));

としてしまうと、実行時に以下のエラーで死にます。

zsh: abort (core dumped)  ./a.exe

なので、以下のように、値がmsの中に存在することがわかっている場合のみ消すようにすると安全です。

auto it = ms.find(42);
if (it != ms.end()) {
    ms.erase(it);
}

参考

Cygwin + ImageMagick を使ってPDFから連番のJPGを生成

Cygwin + ImageMagick を使ってPDFから連番のJPGを生成する方法についてメモします。

準備

Cygwinインストーラを用いて" ImageMagick"と"ghostscript"をインストールします。

そのあと、Cygwinのコンソールで which convertしてみてください。/bin/convert/usr/bin/convertなどと表示されれば ImageMagickを呼び出す準備ができています。

もし/cygdrive/c/Windows/system32/convertWindowsに組み込まれているコマンド)が表示されるようであれば正しく ImageMagickがインストールされていない可能性があります。 ImageMagickをインストールし直すなり、ImageMagickにPATHを通すなりしてください。

処理

PDFの名前をsource.pdfとします。以下のコマンドにより、0001.jpg, 0002.jpg, ... が生成されます。

$ convert source.pdf %04d.jpg

ただ、上記コマンドだと、生成される画像の品質が非常に悪いことがあります。そのときは-density 300などと解像度を指定します。(ハイフンは1個なので気をつけてください)

$ convert -density 300 source.pdf %04d.jpg

参考

`

TopCoderの環境構築メモ

Windows 10にTopCoderのための環境を構築したときの簡易的なメモです。

Javaランタイムのインストール

Java Appletの入手

  • Googletopcoder java appletで検索して出てくるリンクからアプレットをダウンロード。現時点での直リンクはこちら

サイトリストの追加

http://topcoder.com
http://www.topcoder.com
http://arena.topcoder.com
https://topcoder.com
https://www.topcoder.com
https://arena.topcoder.com   
  • 追加後の画面の一例 f:id:minus9d:20190430092319p:plain

greedプラグインの導入

greedプラグインを入れることで、テンプレートを自動挿入したり、手元でのテストが簡単に行えたりが簡単になる。

私の場合は以下のように設定ファイルを書いている。

  • workspaceとして設定したディレクトリに greed.confという名前で以下のファイルを作成
greed.language.cpp.templateDef.source.templateFile = "my_template.cpp"
greed.language.python.templateDef.source.templateFile = "my_template.py"
  • ディレクトリにmy_template.cppという名前で以下のファイルを作成
#include <iostream>
#include <sstream>
#include <string>
#include <cassert>
#include <cmath>
#include <climits>
#include <cstdio>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <algorithm>
#include <functional>
#include <numeric>
#include <iomanip>
#include <cstring>
#include <fstream>

using namespace std;
typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;

#define REP(i,n) for(int i = 0; i < (int)(n); ++i)
#define FOR(i,a,b) for(int i = (a); i < (int)(b); ++i)
#define ALL(c) (c).begin(), (c).end()
#define SIZE(v) ((int)v.size())

#define pb push_back
#define mp make_pair
#define mt make_tuple

using namespace std;

class ${ClassName} {
    public:
    ${Method.ReturnType} ${Method.Name}(${Method.Params}) {
        return ${Method.ReturnType;zeroval};
    }
};

${CutBegin}
${<TestCode}
${CutEnd}
  • ディレクトリにmy_template.pyという名前で以下のファイルを作成
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import array
from bisect import *
from collections import *
import fractions
import heapq
from itertools import *
import math
import re
import string

class ${ClassName}:
    def ${Method.Name}(self, ${Method.Params}):
        return ${Method.ReturnType;zeroval}

${CutBegin}
${<TestCode}
${CutEnd}