メインコンテンツまでスキップ

cublas の使い方メモ

· 約1分
ひかり
Main bloger

この記事は書きかけです。

cublasSetMatrix()

cublasStatus_t
cublasSetMatrix(int rows, int cols, int elemSize,
const void *A, int lda, void *B, int ldb)

ホストメモリー上の行列 A から、GPU メモリー上にある行列 Brow × col の要素をコピーする関数。 各要素は elemSize バイトであり、行列は列優先で格納され、 先頭の次元はそれぞれ ldaldb で指定する。

参考: https://docs.nvidia.com/cuda/cublas/index.html#cublassetmatrix

自作 gem の作り方

· 約4分
ひかり
Main bloger

gem を作成 (bundle gem)

gem_name という gem のテンプレートを作成する場合は以下を実行します。

bundle gem gem_name

bundle gem のオプション

bundle gem にはオプションが存在します。

詳細またはその他のオプションを知りたい場合は Bundler: bundle gem を参照してください。

オプション説明
--exe, -b, --bingem にバイナリ実行ファイルを含めます。
--extgem に C 拡張を含めます。
--mitプロジェクトを MIT ライセンスにします。
--cici サービスを設定します。
--linterリンターとフォーマッターを指定します。

例: リンターに rubocop を使用し、MIT ライセンスでコマンドを含み、C 言語拡張を含む myapp という gem を作成する場合

bundle gem myapp --exe --ext --mit --ci=github --linter=rubocop

プロジェクトの構造

上記コマンドで生成したプロジェクトの構造は以下のようになっています。

myapp
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── bin
│   ├── console
│   └── setup
├── exe
│   └── myapp
├── ext
│   └── myapp
│   ├── extconf.rb
│   ├── myapp.c
│   └── myapp.h
├── lib
│   ├── myapp
│   │   └── version.rb
│   └── myapp.rb
├── myapp.gemspec
└── sig
└── myapp.rbs

各ディレクトリーは以下のようになっています。

  • lib/: ライブラリーのコード (require で呼び出される)
  • ext/: C 言語のソースコード (インストール時にコンパイルされ、require で呼び出される)
  • exe/: コマンドがある

myapp.gemspec がもっとも重要なファイルで、gem の構成が定義されています。 基本的に上記 3 つのディレクトリー (C 言語を使用しない場合は、2 つのディレクトリー) の中にあるファイルと gemspec ファイルを編集します。(必要に応じて Rakefile や README.md も編集します。)

Gemfile は編集しないでください。

gemspec の編集

gem を作るために myapp.gemspec を編集する必要があります。

TODO のある行やホームページの行をコメントアウトし、spec.summary の設定を行えば最低限動作します。

必須である項目を以下に示します。

  • spec.name
  • spec.version
  • spec.authors
  • spec.summary

bundle install コマンドを実行し、エラーがなければ問題ありません。

依存パッケージの追加

gemspec に以下のように追記して依存している gem を追加できます。

  spec.add_dependency "example-gem", "~> 1.0"

gemspec に以下のように追記し開発時に必要な gem を追加できます。

  spec.add_development_dependency "example-gem", "~> 1.0"

詳しくは、class Gem::Specification (Ruby 3.1) リファレンスマニュアルlibrary rubygems (Ruby 3.1 リファレンスマニュアル) を参照してください。

bundle install

bundle install を実行することで、Gemfile および gemspec に記述されている gem がインストールされます。

バージョンの変更

バージョンは、lib/myapp/version.rb に定義されています。

コンパイル

以下のコマンドを実行し、C 拡張をコンパイルします。 このコマンドの実行により、共有ライブラリー lib/myapp/myapp.so が生成されます。

rake compile

コンパイル後、gem に含まれるコマンド実行すると、 エラーなく実行されます。

bundle exec myapp

C 拡張

C 言語で Ruby を拡張することができます。

たとえば、/etc/myapp/myapp.c を以下のように変更します。

void
Init_myapp(void)
{
rb_mMyapp = rb_define_module("Myapp");
+ rb_p(rb_str_new2("Hello, world!"));
}

rake compile でコンパイルを行い、bundle exec myapp を実行すると、"Hello, world!" と表示されます。

この例は、C 言語から Ruby の C API を呼び出し表示するプログラムで、

p "Hello, world!"

と同等です。

Ruby の C API だけではなく、コンピューターにインストールされている共有ライブラリーを扱うことができるため、ラッパーを作成することが可能です。

また、C 拡張により計算が必要な場合に高速化することができます。

ライブラリーの作成

lib/myapp.rb あたりを編集。

新しいファイルを作成した場合は、git add する必要があります。

gem をインストール (rake install)

プロジェクト内の gem がインストールされます。

rake install

gem を公開 (rake release)

gem を公開するには、rubygems のアカウントを作成する必要があります。 リリースするたびに、バージョンを変更する必要があります。

rake release

gem パッケージを生成 (rake build)

プロジェクトから pkg/myapp-x.x.x.gem が作成されます。

rake build

Ubuntu 系の Linux ディストリビューションの自作方法

· 約4分
ひかり
Main bloger

概要

  1. iso ファイル (ディスクイメージ) を展開
  2. squashfs ファイル (/ の中、ファイルシステムイメージ) を展開
  3. (2.) で展開してものに対し、カスタマイズするためのスクリプトを適用
  4. (3.) から squashfs を作成 (mksquashfs コマンド)
  5. (4.) を (1.) に入れて、チェックサムやファイルサイズ、パッケージのリストを更新
  6. (5.) を iso ファイルを作成 (xorriso コマンドを使用)

この流れで、Ubuntu の改造ディストリビューションを作成できます。

用意するもの

  • Ubuntu のイメージ

必要なパッケージのインストール

sudo apt install cd-boot-images-amd64 xorriso

パッケージがないとかでインストールができない場合は以下を実行し再度実行してください。

echo "deb http://cz.archive.ubuntu.com/ubuntu jammy main" | sudo tee -a /etc/apt/sources.list
sudo apt update

展開とマウント

# DISK_IMAGE はディスクイメージのパスです。
DISK_IMAGE=/mnt/d/ubuntu-22.04-desktop-amd64.iso

# RELEASENOTE_URL はリリースノートの URL です。
RELEASENOTE_URL="http://"

# 作業ディレクトリーの作成
mkdir ~/my-distribution
cd ~/my-distribution

# ディスクイメージのシンボリックリンクを作成します。
ln -s $DISK_IMAGE image.iso

# ディスクイメージをマウント
# 警告が出ますが無視してください。
mkdir mnt
sudo mount -o loop image.iso mnt

# ディスクイメージのコピー
# マウントした場所は書き換えができないのでコピーします。
# ただし、ディストリビューションのファイルシステムである /casper/filesystem.squashfs は除外してコピーします。
mkdir disk
rsync -P -a --exclude=/casper/filesystem.squashfs mnt/ disk

# ファイルシステムイメージのマウント
mkdir mntfs
sudo mount -t squashfs -o loop mnt/casper/filesystem.squashfs mntfs

# ファイルシステムをコピー
# マウントした場所は書き換えできないので、コピーします。
mkdir squashfs
sudo rsync -P -a mntfs/ squashfs

# マウントは不要になったのでアンマウントします。
sudo umount mntfs
sudo umount mnt
rm -r mntfs mnt

# シンボリックリンクも不要なので削除します
rm image.iso

# リリースノートの URL を設定します。
echo $RELEASENOTE_URL | sudo tee disk/.disk/release_notes_url

# ディスク情報を設定します。
today=$(date +"%Y%m%d")
echo -n "MyDistribution 22.04 LTS \"Jammy Jellyfish\" - Release amd64 ($today)" | tee
echo -n "MyDistribution 22.04 LTS \"Jammy Jellyfish\" - Release amd64 ($today)" | sudo tee disk/.disk/info

# インストーラーの言語を日本語に設定します。
cat | sudo tee -a disk/preseed/ubuntu.seed <<EOF
d-i debian-installer/language string ja
d-i debian-installer/locale string ja_JP.UTF-8
d-i keyboard-configuration/layoutcode string jp
d-i keyboard-configuration/modelcode jp106
d-i keyboard-configuration/layout select Japanese
d-i keyboard-configuration/variant select Japanese
EOF

# grub.cfg の日本語化
splash=$(echo "splash --- debian-installer/language=ja" \
"debian-installer/locale=ja_JP.UTF-8" \
"keyboard-configuration/layoutcode?=jp" \
"keyboard-configuration/modelcode?=pc105")
sudo sed -i "s#splash ---#$splash#" disk/boot/grub/grub.cfg

カスタマイズするためのスクリプトの割り当て

# MyDistribution.sh は Ubuntu をカスタマイズするスクリプトです。
chroot squashfs /bin/bash MyDistribution.sh

ファイルシステムの作成

# パッケージ一覧を書き込み
sudo chroot squashfs/ dpkg-query -W --showformat='${binary:Package}\t${Version}\n' |\
tee disk/casper/filesystem.manifest

# ファイルシステムのサイズを書き込み
sudo du -B 1 -s squashfs/ | cut -f1 | sudo tee disk/casper/filesystem.size

# ファイルシステムのイメージ化
sudo mksquashfs squashfs/ disk/casper/filesystem.squashfs -xattrs -comp xz
sudo rm disk/casper/filesystem.squashfs.gpg

# md5sum.txt を出力
cd disk
find . -type f -not -name 'md5sum.txt' -not -path './boot/*' -not -path './EFI/*' -print0 | xargs -0 md5sum | sudo tee md5sum.txt
md5sum ./boot/memtest86+.bin | sudo tee -a md5sum.txt
md5sum ./boot/grub/*.cfg | sudo tee -a md5sum.txt
cd ..

ディスクイメージの作成

VOLUME_ID="MyDistribution"
OUTPUT_ISO="mydistribution-22.04-desktop-amd64.iso"

xorriso \
-as mkisofs \
-volid "$VOLUME_ID" \
-o "$OUTPUT_ISO" \
-J -joliet-long -l \
-b boot/grub/i386-pc/eltorito.img \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
--grub2-boot-info \
--grub2-mbr /usr/share/cd-boot-images-amd64/images/boot/grub/i386-pc/boot_hybrid.img \
-append_partition 2 0xef /usr/share/cd-boot-images-amd64/images/boot/grub/efi.img \
-appended_part_as_gpt \
--mbr-force-bootable \
-eltorito-alt-boot \
-e --interval:appended_partition_2:all:: \
-no-emul-boot \
-partition_offset 16 \
-r \
disk/

QEMU で起動してみる

QEMU をインストールしていない場合

sudo apt install -y qemu-system-x86

LiveCD を起動する

sudo qemu-system-x86_64 -m 4G -cdrom mydistribution-22.04-desktop-amd64.iso -boot d --enable-kvm -usb -smp 6

仮想ディスクにインストールする場合

qemu-img create -f qcow2 disk.qcow2 32G
sudo qemu-system-x86_64 -hda disk.qcow2 -m 4G -cdrom mydistribution-22.04-desktop-amd64.iso -boot d --enable-kvm -usb -smp 6

Firefox のビルドをインストール

· 約1分
ひかり
Main bloger

Ubuntu 22.04 は snap 版の Firefox がインストールされているらしく、 環境によって起動ができなかったので、ビルド済み Firefox のインストールの方法をメモ。

apt / snap 版の Firefox のアンインストール

sudo apt purge firefox
sudo snap remove firefox

Firefox のビルドをインストール

# ダウンロード
wget "https://download.mozilla.org/?product=firefox-latest-ssl&os=linux64&lang=ja" --trust-server-names

# 展開
tar xvf firefox-*.tar.bz2

# 配置
sudo cp -r firefox /usr/lib

# 実行ファイルのシンボリックリンクを作成
sudo ln -s /usr/lib/firefox/firefox /usr/bin/firefox

# デスクトップファイルをダウンロードし配置
sudo mkdir -p /usr/share/applications
sudo wget https://bit.ly/3Mwigwx -O /usr/share/applications/firefox.desktop

Ubuntu で gsettings を使用し Dock の設定を行う

· 約2分
ひかり
Main bloger

スクリプトで Dock の設定したいときや、SSH で設定したいときに使う。

Dock を自動的に隠す

設定する値説明
true自動的に隠さない
false自動的に隠す

例: Dock を自動的に隠す

# 現在の設定
$ gsettings get org.gnome.shell.extensions.dash-to-dock dock-fixed
true

$ gsettings set org.gnome.shell.extensions.dash-to-dock dock-fixed false

パネルモード

Dock を画面の端まで引き伸ばして表示。

設定する値説明
true引き延ばさない
false引き延ばす

例: パネルを引き延ばさない

# 現在の設定
$ gsettings get org.gnome.shell.extensions.dash-to-dock extend-height
true

$ gsettings set org.gnome.shell.extensions.dash-to-dock extend-height false

アイコンサイズの変更

設定する値説明
数値アイコンサイズ

例: アイコンサイズを 30 に変更

# 現在の設定
$ gsettings get org.gnome.shell.extensions.dash-to-dock dash-max-icon-size
48

$ gsettings set org.gnome.shell.extensions.dash-to-dock dash-max-icon-size 30

Dock の表示位置を変更

「設定」では設定ができない 'TOP' が設定可能。上に微妙な隙間ができる。

設定する値説明
LEFT
BOTTOM
RIGHT
TOP

例: Dock の表示位置を下に設定

# 現在の設定
$ gsettings get org.gnome.shell.extensions.dash-to-dock dock-position
'LEFT'

$ gsettings set org.gnome.shell.extensions.dash-to-dock dock-position 'BOTTOM'

ゴミ箱の表示

設定する値説明
true表示
false非表示

例: ゴミ箱を非表示に設定

# 現在の設定
$ gsettings get org.gnome.shell.extensions.dash-to-dock show-trash
true

$ gsettings set org.gnome.shell.extensions.dash-to-dock show-trash false

OpenLDAP の slappasswd で生成される SSHA とは

· 約1分
ひかり
Main bloger

slappasswd コマンドとは

slappasswd コマンドは OpenLDAP 用のパスワードを生成するコマンドで、 デフォルトでは SSHA を用いて、パスワードをハッシュ化する。

認証の仕組み

SSHA では生成されたハッシュの末尾 4 バイトがソルトとなっており、 入力されたパスワードと保存されているソルトからハッシュを生成し、 保存されているハッシュと一致するかどうかで認証を行う。

以下のプログラムでは、 適切なパスワード (例: admin) を与えると、元のハッシュと生成されたハッシュが一致する。

require 'base64'
require 'digest'

pass = 'admin'
ssha = '{SSHA}23AUBfRZytVFNpe7onuFhyCSJOHRzCWh'
ssha =~ /{.+}(.+)/
salt256s = Base64.decode64(Regexp.last_match(1)).unpack('C*')[-4..-1]

salt = salt256s.pack('C*')
b_ssha = Digest::SHA1.digest(pass + salt)
Base64.strict_encode64(
(b_ssha.unpack('C*') + salt256s).pack('C*')
)

Blog 環境の移行

· 約1分
ひかり
Main bloger

ブログの環境を jekyll から Docusaurus に移行しました。 アクセスの多い記事に関しては jekyll から移行予定です。

Python で極値の検出

· 約2分
ひかり
Main bloger

概要

信号の極値を検出する。

信号の生成

例として疑似的な信号を生成する。

  • 3 [Hz] の信号 + 0.01 [Hz] の信号 + ノイズ
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from scipy import signal

t = np.arange(30 * 100) / 100
x = np.sin(2 * np.pi * t / 3) + np.random.randn(len(t)) * 0.2 + np.sin(2 * np.pi * t / 100)
df = pd.DataFrame({'Data': x}, index=pd.to_datetime(t, unit='s').time)

fig, ax = plt.subplots()
df.plot(ax=ax, xlim=['00:00:00', '00:00:10'])
plt.show()

tmp

信号の性質を調べる

def acorr(df: pd.DataFrame, ra: int = 3, fs=100):
x = np.correlate(df.Data.values, df.Data.values, mode='full')
t = (np.arange(len(x)) - len(x) / 2 + 0.5) / fs
x /= x.max()
fig, ax = plt.subplots()
ax.set_xlim(-ra, ra)
ax.set_ylim(0, 1)
ax.plot(t, x)
ax.set_title('Autocorrelation')
ax.grid(axis='x')
ax.set_xticks(np.linspace(-ra, ra, 2 * ra + 1))
plt.show()

acorr(df)

主な信号は 1/3 [Hz] であることがわかる。そのため、1/3 [Hz] でローパスフィルターをかける。

tmp

ローパスフィルターをかけ、極値の検出

ローパスフィルターをかけ、極値を検出できるようにする。

1/3 [Hz] でローパスフィルターをかけても正しく検出されない場合は、 周波数を下げていく。

tmp

fs = 10
lpf = 0.1
b, a = signal.butter(5, lpf / fs * 2, 'low')
df['Filter'] = signal.filtfilt(b, a, df.Data.values)
max_idx = signal.argrelmax(df['Filter'].values)
min_idx = signal.argrelmin(df['Filter'].values)

df['max_index'] = False
df.iloc[max_idx[0], 2] = True
df['min_index'] = False
df.iloc[min_idx[0], 3] = True

fig, ax = plt.subplots()
df.plot(ax=ax)
ax.set_xlim(['00:00:00', '00:00:30'])
ax.scatter(
df.loc[df['max_index'], ['Filter']].index,
df.loc[df['max_index'], ['Filter']],
color='tab:orange',
zorder=3)
ax.scatter(
df.loc[df['min_index'], ['Filter']].index,
df.loc[df['min_index'], ['Filter']],
color='tab:green',
zorder=3)
plt.show()

C 言語で 2 次元配列を扱う

· 約1分
ひかり
Main bloger

行数・列数、数値の入るメモリを構造体でまとめると扱いやすい。

#include <stdio.h>
#include <stdlib.h>

typedef struct {
float *data;
int col_size;
int row_size;
} Mat;

void MatInit(Mat *mat, int row_size, int col_size) {
mat->row_size = row_size;
mat->col_size = col_size;
mat->data = (float *)calloc(row_size * col_size, sizeof(float));
}

float *MatAt(Mat *mat, int i, int j) {
return mat->data + i * mat->col_size + j;
}

void MatFree(Mat *mat) { free(mat->data); }

int main(void) {
Mat mat;
MatInit(&mat, 30, 5); // 30 行 5 列 の行列を初期化
*MatAt(&mat, 0, 0) = 50; // 行 0 列 0 に 50 を代入
printf("%f\n", *MatAt(&mat, 0, 0)); // 行 0, 列 0 の数値を表示

MatFree(&mat);

return 0;
}

Visual Studio Code で Got bad result from install script. のエラーの対処

· 約1分
ひかり
Main bloger

vscode で ssh をしようとしたが、Got bad result from install script. というエラーが起き、接続できない。

何故かコマンドプロンプトも起動しない。

解決法

レジストリ エディターを開き、HKEY_CURRENT_USER\Software\Microsoft\Command Processor にある AutoRun の値を空にした。