OmniAICreator/Qiita-1.07M huggingface dataset:
代入と浅いコピーと深いコピー

自分のために書いたのであまり参考にはなりません
```python
from copy import deepcopy

s = [1 , 2 ,[3, 4]]
#代入
s1 = s

#浅いコピー
s2 = s.copy()

#深いコピー
s3 = deepcopy(s)
```
s内の値が1をとる部分に100を代入してみる
```python

s[0] = 100

print("s = %s \ns1 = %s \ns2 = %s \ns3 = %s" % (s, s1, s2, s3))


#出力
"""
s = [100, 2, [3, 4]]
s1 = [100, 2, [3, 4]]
s2 = [1, 2, [3, 4]]
s3 = [1, 2, [3, 4]]
"""
```
s1が変化し、s2とs3は変化しなかった。

次にs内の値が3をとる部分に300を代入してみる
```python

s[2][0] = 300

print("s = %s \ns1 = %s \ns2 = %s \ns3 = %s" % (s, s1, s2, s3))

#出力
"""
s = [100, 2, [300, 4]]
s1 = [100, 2, [300, 4]]
s2 = [1, 2, [300, 4]]
s3 = [1, 2, [3, 4]]
"""
```
s1とs2が変化し、s3は変化しなかった。


代入は「完全に」同じオブジェクトを参照，
浅いコピーは「リストの要素」は同じオブジェクトを参照，(sとs2自体は違うオブジェクトを参照)
深いコピーは違うオブジェクトを参照しているためこのようなことが起こる。

もう少し詳しく話そう。
この世には「イミュータブル」なオブジェクトと「ミュータブル」なオブジェクトがある。

「イミュータブル」なオブジェクトの例・・・文字列、数字、タプル、
「ミュータブル」なオブジェクト・・・上記以外大体そう

イミュータブルなオブジェクトは値を変えるときに新しいオブジェクトを生成するのでidが変わり、ミュータブルなオブジェクトは値を変えてもidは変わらない。
個人的なイメージとしてはイミュータブルなオブジェクトの値は賃貸、ミュータブルなオブジェクトの値は持ち家、idは住所である。持ち家はリフォームできるけど賃貸は引っ越さないとねってことである。知らんけど。

```python
n = 128
l = [1,2,3]

print('n = %i, id(n) = %i \nd = %s, id(l) = %i'% (n, id(n),l, id(l)))

#出力
"""
n = 128, id(n) = 140705162318600 
d = [1, 2, 3], id(l) = 1904532569792
"""

n += 1
l[2] = 200

print('n = %i, id(n) = %i \nd = %s, id(l) = %i'% (n, id(n),l, id(l)))
#出力(id(n)は変化しているが、id(l)は変化していない)
"""
n = 129, id(n) = 140705162318632
d = [1, 2, 200], id(l) = 1904532569792
"""
```

このせいで、次のような現象が起こる

```python
#イミュータブル
a = 128
b = a
a += 1

print('a = %d, b = %d'% (a, b))
# a = 129, b = 128

#ミュータブル
c = [1, 2, 3]
d = c
c[2] = 300

print('c = %s, d = %s'% (c, d))
# c = [1, 2, 300], d = [1, 2, 300]
```

イミュータブルなオブジェクトの場合、最初はaとbは同じオブジェクトを参照していてidも同じだったが、aに1を足した時点でaは新しいオブジェクトを生成しているので、違うオブジェクトを参照してるということになる。よって、aとbは異なる値をとる。
しかし、ミュータブルなオブジェクトの場合、cの値が変化しても、同じオブジェクトを参照しているということになり、dの値も変化する。

浅いコピーの話に戻ろう。
浅いコピーはリストの要素は同じオブジェクトを参照しているということだった。
sの要素のうちs[0]、s[1]はイミュータブルであるため、s2[0]、s[1]の値は変化しない。
しかし、s[2]はミュータブルであるため、s2[2]の値は変化する。
```python
s = [1, 2, [3, 4]]
s2 = s.copy()

s[0] = 100
s[2][0] = 300

print('s = %s, s2 = %s' % (s, s2))
# s = [100, 2, [300, 4]], s2 = [1, 2, [300, 4]]
```

参考にしたサイト
[Pythonのcopyとdeepcopyについて](https://qiita.com/Kaz_K/items/a3d619b9e670e689b6db)
【PHPUnit】テストクラスに汎用的なBaseTestClassを作ろう

## はじめに
各テストクラスで有効化処理書いたり面倒なので、
テストクラスの継承元のBaseTestClassを作って楽がしたい。

## コード
<details><summary>BaseTestCase</summary>

```
<?php

namespace Tests;

use Tests\TestCase;
use ReflectionClass;

class BaseTestCase extends TestCase
{
    protected $testsDirPath;

    public function __construct()
    {
        parent::__construct();
        return $this->testsDirPath = __DIR__;
    }

    /* Execute a private or protected function with params.
    *
    * @param  object $instance
    * @param  string $functionName
    * @param  array  $params
    * @return mixed　
    */
    protected function executePrivateFunction(object $instance, string $functionName, array $params = [])
    {
        $method = $this->enablePrivateFunction($instance, $functionName);
        return $method->invokeArgs($instance, $params);
    }

    /* Enable a private or protected function
    *
    * @param  object $instance
    * @param  string $functionName
    * @return object $method
    */
    protected function enablePrivateFunction(object $instance, string $functionName): object
    {
        $reflection = new ReflectionClass($instance);
        $method = $reflection->getMethod($functionName);
        $method->setAccessible(true);
        return $method;
    }

    /* Get a private or protected property
    *
    * @param  object $instance
    * @param  string $propertyName
    * @return mixed
    */
    protected function getPrivateProperty(object $instance, string $propertyName)
    {
        $property = $this->enablePrivateProperty($instance, $propertyName);
        return $property->getValue($instance);
    }

    /* Set a private or protected property
    *
    * @param  object $instance
    * @param  string $propertyName
    * @param  mixed  $value The value you want to overwrite.
    * @return mixed
    */
    protected function setPrivateProperty(object $instance, string $propertyName, $value)
    {
        $property = $this->enablePrivateProperty($instance, $propertyName);
        return $property->setValue($instance, $value);
    }

    /* Enable a private or protected property
    *
    * @param  object $instance
    * @param  string $propertyName
    * @return object $method
    */
    protected function enablePrivateProperty(object $instance, string $propertyName): object
    {
        $reflectionClass = new ReflectionClass($instance);
        $property = $reflectionClass->getProperty($propertyName);
        $property->setAccessible(true);
        return $property;
    }
}
```

</details>

## 各function説明
### executePrivateFunction()
privateやprotectedなfunctionをそのままテスト実施するとエラー出るので有効化したついでにテスト自体も実行する

### enablePrivateFunction()
↑のfunctionを有効化している部分

### getPrivateProperty()
privateやprotectedなpropertyを取得するfunction。ゲッター

### setPrivateProperty()
privateやprotectedなpropertyにはそのままだとセットできないのでセッター

### enablePrivateProperty
↑のpropertyを有効化している部分
pyenv+venvでpythonの仮想環境バージョン管理

# pythonのバージョンを管理しながら仮想環境構築したので、備忘録
### やったこと
1. pythonの複数バージョンをpyenvでインストール。
2. 指定のディレクトリで使えるpythonのバージョンを指定。
3. 指定したバージョンでvenvで仮想環境構築。
*macOSでzshです。
### 一つずつ説明を書きます。

## 1. pythonの複数バージョンをpyenvでインストール。
- まずpyenvをインストール。homebrewを使ってます。
```zsh  
brew install pyenv
```
- シェルの設定ファイルにpyenvを追加
```zsh
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv init -)"
```
上記のスクリプトを下記のようにターミナル上でファイルを開いてコピペして、ファイルを変更する。
```zsh
nano ~/.zshrc
```
出力は以下。ここにコピペして保存。
```zsh
  UW PICO 5.09              File: /Users/yamamotoryoichi/.zshrc                 

eval "$(rbenv init -)"
export PATH="/usr/local/opt/mysql@5.7/bin:$PATH"
export PATH=$HOME/.nodebrew/current/bin:$PATH
export PATH="$PATH:`yarn global bin`"
export JAVA_HOME=`/usr/libexec/java_home -v 15.0.1`
export PATH="/usr/local/opt/python@3.13/libexec/bin:$PATH"
# pyenv のパスを優先する
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/shims:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv init -)"


^G Get Help  ^O WriteOut  ^R Read File ^Y Prev Pg   ^K Cut Text  ^C Cur Pos   
^X Exit      ^J Justify   ^W Where is  ^V Next Pg   ^U UnCut Text^T To Spell  
```

- 設定を反映させる。
```zsh
source ~/.zshrc
```
これでターミナル上で`pyenv`コマンドが使える。

- `pyenv`コマンドを使って必要なpythonバージョンをインストール。
＊勝手なイメージだとpyenvフォルダの中にpythonバージョンごとにフォルダを作るイメージ。そのためhomebrewでpythonをインストールしているのとは別のフォルダ内にpythonのフォルダが作られる感じ。
```zsh
pyenv install 3.9.7
pyenv install 3.8.12
```
- インストールされているかを確認。
```zsh
pyenv versions

#出力
python 3.9.7
python 3.8.12
```
となっているはず。
## 2. 指定のディレクトリで使えるpythonのバージョンを指定。
- 仮想環境を作りたいディレクトリへ移動しpyenvでそのディレクトリ内で使えるpythonバージョンを指定。
```zsh
cd my_project
pyenv local 3.9.7
```
これで、`my_project`ディレクトリ内ではPython 3.9.7が使用されるようになります。
## 3. 指定したバージョンでvenvで環境構築。
- 仮想環境を構築。
この時`python`コマンドを使用しているが、`python --version`でバージョンを確認してみてもわかる通り、先ほど指定したバージョンになっている。
```zsh 
python -m venv your_venv_name
```
これで仮想環境が構築完了。

## ちなみに
```zsh 
pyenv global 3.9.7
```
のようにすればグローバル（どこのディレクトリ）のpythonのバージョンを変えられるらしい。


書籍のサンプルコードが動かなかったため、四苦八苦しました。
Ubuntu22.04にcolimaをインストールする

Dockerを動かす手段の1つとして、`colima`があります。`colima`をmacOSで動かす手順は広く知られていますが、Ubuntu22.04で動かす方法があまり広まっていないので、この度、Qiita記事にまとめてみました。

## 手順

1. Ubuntu22.04にNixをインストールする
2. Nixで`colima`をインストールする
3. Docker ComposeとBuildxをプラグインとして導入する

順に見ていきましょう。

### 1. Ubuntu22.04にNixをインストールする

下記のDeterminate Nix Installerを使用します。

https://github.com/DeterminateSystems/nix-installer

```bash
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
```

途中で`sudo`権限を求められます。また、設問に答える必要があります(`Y`でOK)。

メッセージで表示されますが、最後に下記を実行します。

```bash
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
```

### 2. Nixで`colima`をインストールする

下記の手順は古いです。

https://github.com/abiosoft/colima

代わりに下記のコマンドを使います。

```bash
nix profile install nixpkgs#colima
```

### 3. Docker ComposeとBuildxをプラグインとして導入する

基本的には下記に沿って、都度、最新版の手順を実行していきます。

https://zenn.dev/fastsnowy/articles/fd2920d4844bc9

#### Docker Composeをインストールする

https://docs.docker.com/compose/install/linux/#install-the-plugin-manually

最後に `.bashrc` に下記を足します。

```bash:.bashrc
export DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
```

#### Buildxをインストールする

下記から最新版のURLを取得します。

https://github.com/docker/buildx/releases/

下記のようにコマンドを入力します(プラットフォームは `linux-amd64` としています)。

```bash
curl -SL https://github.com/docker/buildx/releases/download/v0.21.2/buildx-v0.21.2.linux-amd64 -o $DOCKER_CONFIG/cli-plugins/docker-buildx
```

```bash
chmod +x $DOCKER_CONFIG/cli-plugins/docker-buildx
docker buildx version
```

バージョンが表示されればbuildxの導入は完了です。

その後、次のコマンドを実行して、`buildx`をデフォルトにします。

```bash
docker buildx install
```
NetlifyでAuth.jsを使うと「UntrustedHost: Host must be trusted」エラーが発生する問題


# 発生した現象

Netlify 上で Next.js + Auth.js（NextAuth.js）を使用しようとした際に、UntrustedHost: Host must be trusted というエラーに悩まされました。

ローカル環境では問題なく動作するのに、Netlify にデプロイするとエラーが発生していました。

# version

Next.js: 15.1.7
next-auth: ^5.0.0-beta.22,
Prisma: ^6.4.1
TypeScript: ^5.7.3

# エラー内容

```
[auth][error] UntrustedHost: Host must be trusted.
URL was: https://you-lift.netlify.app/api/auth/providers
```

このエラーの原因は、Auth.js（NextAuth.js）が Netlify のデプロイ先 URL を「信頼されたホスト」として認識していない ことにあります。
NEXTAUTH_URL は正しい URL を設定済みです...

# 解決策

Auth.js の`auth.ts`という設定ファイルで、trustHost: true を追加するだけで解決しました。

```ts
import NextAuth, { Session } from "next-auth";
import Google from "next-auth/providers/google";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { prisma } from "../prisma";

export const authConfig = {
  adapter: PrismaAdapter(prisma),
  providers: [Google],
  pages: {
    signIn: "/login",
  },
  callbacks: {
    authorized: async ({ auth }: { auth: Session | null }) => {
      return !!auth;
    },
  },
  trustHost: true, // ← ここを追加！！
};

export const { handlers, signIn, signOut, auth } = NextAuth(authConfig);
```
C#でPDFからページを削除する方法

PDF文書に余計な内容のページが含まれている場合、残りの内容が正確で、焦点が合っていて、文書の意図された目的と一致していることを確実にするために、これらのページを削除することが必要です。この記事では、[無料の.NET PDFライブラリ](https://www.e-iceblue.com/Introduce/free-pdf-component.html)を使用して、プログラムでPDFからページを削除する方法を学びます。

## 無料ライブラリーのインストール
使用されているフリーのライブラリは [**Free Spire.PDF for .NET**](https://www.e-iceblue.com/Introduce/free-pdf-component.html)と呼ばれ、以下のリンクからダウンロードするか、Nuget経由で直接インストールすることができます。

https://www.e-iceblue.com/Download/download-pdf-for-net-free.html

無償のPDF APIは商用・個人用を問わず使用できますが、特定のページ制限があります。詳しくは

https://www.e-iceblue.com/Introduce/free-pdf-component.html


## C# を使用してPDFページを削除
**`PdfDocument.Pages.RemoveAt()`** メソッドは、PDFファイルから指定されたページを削除します。

サンプルC#コード:
```csharp
using Spire.Pdf;

namespace RemovePage
{
    class Program
    {
        static void Main(string[] args)
        {
            //PdfDocumentオブジェクトを作成する
            PdfDocument document = new PdfDocument();

            //PDF文書をロードする
            document.LoadFromFile(@"sample.pdf");

            //指定されたページを削除する
            document.Pages.RemoveAt(1);

            //別のファイルに保存する
            document.SaveToFile("result.pdf");
        }
    }
}
```

![DeletePDF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/1a68a9f0-603e-4ea0-aa12-66b3673e10b4.png)

* * *
無料の.NET PDFライブラリを使用すると、[PDF内のページを回転させ](https://www.e-iceblue.com/Tutorials/Spire.PDF/Spire.PDF-Program-Guide/Page-Setting/How-to-rotate-the-PDF-file-in-C.html)、[PDFのページサイズを変更し](https://www.e-iceblue.com/Tutorials/Spire.PDF/Spire.PDF-Program-Guide/Page-Setting/How-to-change-PDF-page-size-in-C.html)、[PDF文書を結合/分割し](https://www.e-iceblue.com/Tutorials/Spire.PDF/Spire.PDF-Program-Guide/NET-Split-PDF-Simply-Split-PDF-Document-to-Multiple-Files-with-C-VB.NET.html)、[PDF文書からテキストや画像を抽出する](https://www.e-iceblue.com/Tutorials/Spire.PDF/Spire.PDF-Program-Guide/How-to-Extract-Text-from-PDF-Document-with-C-/VB.NET.html)ことなどもできます。
【中学生でも分かる！】クリーンアーキテクチャをざっくり理解してみる。

## クリーンアーキテクチャとはずばり
クリーンアーキテクチャとは、「ソフトウェアを整理整頓するための設計手法」！
プログラムの中身を役割ごとにきれいに分けて、変更しやすく、わかりやすく、トラブルが起きにくくする仕組みのこと。
## 日常生活での具体例(学校の部活動で例えてみる)

・指揮者（顧問の先生や指揮担当）
全体の演奏をまとめている。演奏の曲やテンポ、音量とかもここで決まる。
→クリーンアーキテクチャではこれが「中心部（コア）」にあたる。アプリの「本質的なルール」を担当している。

・演奏者（部員）
実際に楽器を演奏する。指揮者の指示に従って自分のパートを担当する。
→クリーンアーキテクチャでは「ビジネスロジック」「ユースケース」と呼ばれ、指揮者が決めたルールを実現する部。

・楽器（トランペット、サックス、ドラム）
部員が実際に音を出すために使う。
→クリーンアーキテクチャでは、「外部インターフェイス」、「フレームワーク」、「データベース」に相当。

・楽譜（曲の楽譜）
演奏者が演奏するときの具体的な指示！
→クリーンアーキテクチャではインターフェイスの役割を果たしている。
[初心者]LinuxでHTTPサーバーを作ったときに覚えたこと備忘録

# CLI
コマンドラインインターフェイスの略
Linuxとかによくあるコマンドを打って目的の操作をする画面
反対は**GUI**

# sudo
今ログインしてるユーザーと違う権限でコマンドを実行するコマンド

# apt update
今回Apacheですがインターネット経由で必要なソフトをダウンロードするために目次（レストランとかのメニューみたいなもの）を新しいものにして売り切れとか新作とかを見つけられるようにする

# apt install xxx
目次から指定したソフトをダウンロード＆インストールする

# cd
今いるフォルダーを移動する（GUIで言うとフォルダーをたどって目的のフォルダーへたどること）

# touch
空のファイルを新しく作る

# Apachの特徴
/var/www/html　というフォルダーにファイルを配置するとブラウザー経由で見ることができる
CISSPに合格した話

先日（2024年4月25日）CISSPを受験し、合格したのでこちらも少しだけまとめようと思います。
※[note](https://note.com/yjinyo/n/n5f48ee481de6)からの移行記事になります。

# 筆者の自己紹介
筆者は受験当時は社会人9年目でした。
業務経験としては、セキュリティ製品の導入、運用、プリセールス等を行っておりました。

R5年秋の情報処理安全確保支援士に合格したので、次はCISSPを受験しようと思いました。
こちらで勉強した内容もCISSPの試験では活きたと感じております。

https://qiita.com/YJinyo/items/3535b6fc5bcec680ce94

# CISSPとは
CISSP(Certified Information Systems Security Professional)とは、ISC2（International Information Systems Security Certification Consortium）が認定を行っている国際的に認められた情報セキュリティ・プロフェッショナル認定資格です。
詳細は下記をご覧ください。

https://japan.isc2.org/cissp_about.html

# 勉強スケジュール
2024年1月～：インプットを中心（教材は後ほど記載）
2024年3月～：公式問題集を解く

# 勉強方法
私はCISSPのトレーニングには参加していないので自力で勉強を進めておりました。
下記の資料やサイト等を利用して勉強を進めました。

## Udemy
PIEDPINさんの講座が各ドメインごとに提供されているため、こちらを8ドメインすべて購入しました。
※Udemyでは定期的にセールをやっているため、セール時に購入されるのがおすすめです。

https://www.udemy.com/course/piedpin_cissp-domain1/?couponCode=ST2MT43024
こちらは初期のころに流し見をして、試験2週間前にもう一度見るような形をとりました。

## CISSP勉強ノート
CISSPの用語等が分かりやすくまとめられているサイトです。
Udemyの講座の方では少しだけ日本語に違和感があった部分もあるので、それをこちらで紐づけて確認するようなことを行っておりました。

https://tex2e.github.io/blog/security/cissp-notes

## CISSP公式問題集
CISSPの公式問題集です。

https://www.amazon.co.jp/dp/B08C7J6SR5?tag=note0e2a-22&linkCode=ogi&th=1&psc=1

CISSPの問題集についてはすべてを3周くらい実施しました。
各ドメインの正答率は下記のような形でした。
昨年末に「とりあえず勉強してないけど解いてみるか！」で解いた結果はさんざんでした…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4029476/cbf05c0d-b23c-4e47-b150-40a313a274fe.png)

## Anki
上記でご紹介した教材の単語をAnkiというアプリに入れて隙間時間に確認しておりました。
iPhoneのアプリは有料ですが、私は購入させていただきました。

https://apps.ankiweb.net/

# 試験当日
試験時間は8時開始、7:30集合で会場はPPC新宿でした。
個人的に少し会場から家まで距離があるため5時起き6時出発のようなスケジュールでした。

会場には7:30に到着し、そこから手続きやトイレを済ませて試験場へ入室しました。

NDAがあるため、試験内容については記載できないのですが、私は試験を40分ほどで終了してしまいました。
相性もあるかもしれないですが、個人的には情報処理安全確保支援士の方が難しく感じました。

手ごたえは感じつつも、結果が印刷されている紙を見るまでは少し緊張しておりました。
「おめでとうございます」の文字を見て安心したと同時に、今の会社では合格時にのみ試験費用が負担されるので「お金が戻ってくる」という安堵もありました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4029476/a84922d7-b6ae-4057-a5a1-8abe10d58f2b.png)

# 感想
今の会社ではCISSPホルダーの方と一緒に仕事をしており、リスクアセスメントやセキュリティ戦略立案などを行っていたため、非常にその経験が活きたように思いました。

「先輩だったらこう考えるよな」や「こうやって進めてきたよな」みたいなことを考えることができたの今の環境に感謝しております。

次はエンドースが終わったら、そこについても書こうかと思います。

長文をここまで読んでいただきありがとうございました。
俺得、生成AIの為のプロンプトメモ

# 生成AIのためのプロンプトメモ

本記事では、生成AIを活用してコードの修正やメール返信文の作成を効率化するためのプロンプト例を紹介します。

---

## 1. コード修正用プロンプト

以下は、特定の条件に沿ってコードを修正するプロンプトの例です。  
**ポイント**  
- **修正箇所のみ**を出力するように指示  
- 「条件」と「コード」のセクションを明確に分けることで、AIが修正すべき部分を認識しやすくしています。

### プロンプト例
```text
以下のコードを条件通りに修正してください。

# 条件
- 修正箇所のみ教えてください。
- 

# コード
#```python
 (ここに対象のコードを記述)
 (例: 関数名や変数名の修正が必要な箇所など)
#```
```
コードブロックにするため[```]を使う 

---

## 2. メール返信文作成用プロンプト

次に、お客さんからのメールに対する返信文を生成するためのプロンプト例です。  
**ポイント**  
- お客さんからのメールと、返信文のテンプレート部分を明示  
- 実際のメール内容を添付することで、文脈に沿った適切な返信をAIに促します。

### プロンプト例

```text
お客さんの返信として適切な文章になるように修正してください。

# お客さんからのメール
[ここにメールを添付]

# 私が書いたお客さんのメールに対する返信文
[ここに入力]
```

---

## まとめ

生成AIを利用したプロンプト設計は、タスクを効率化し、作業ミスを減らす強力なツールとなります。  
本記事で紹介したプロンプト例とコツを参考に、実際の業務や開発現場で活用してみてください。

Happy Prompting!
[初心者]Ubuntsuを使ってhttpサーバーを作る

今回は、ド初心者の私がUbuntsuを使ってhttpサーバーを作ってみたときの手順を書いていこうと思います。
ちょいちょいトラブルにぶち当たりもしたので、その時に試したことも含めて書き起こしています。

# ゴール
- HTTPサーバーを動かす（高性能である必要はない）
- Linuxの操作に慣れること、調べながら進める経験を積むことが大事

# 手順のイメージ
1. Linuxにログインして環境確認
1. 必要なソフトウェアをインストール
1. 簡単なHTTPサーバーを立ててみる
1. 動作確認

# 環境
- Windows 11
- Ubuntu 22.04 LTS
- Apache2

# やってみる
## WSLをインストール
①以下の記事を参考にWSLをインストールする

https://zenn.dev/shz/articles/660cf9ee905bbe


下記のコマンドすると、導入できるLinuxの種類が出てくる。
```
wsl --list --online
```

## Ubuntsuを入れてみる
①下記のコマンドを入れてUbuntsuをインストール
```
wsl --install Ubuntu-22.04
```

② **Installation successfull!** となったら完了

③以降はスタートメニューから起動もできる。
 exitと入力してEnterす津と画面が閉じれる。

 ## Apacheのインストール
 こちらの記事を参考にしながら進めました。
 
 https://qiita.com/shutx/items/810c8aa21c8cd3c16b25
 
①以下のコマンドを打つ
```
$ sudo apt update
$ sudo apt -y install apache2
```

インストールができたら以下のコマンドで確認
```
apache2 -v
```

### ここでトラブル。
参考記事の「ブラウザでサーバのローカルIPアドレス（取得済みドメインでも可）にアクセスする」が私にはピンとこなかったため、いろいろ手探りですすめていきました。

#### **やったこと①**
Apacheが動いているか確認
```
sudo systemctl status apache2
```
→ `active (running)` になったので問題なさそう

#### やったこと②
サーバーのローカルIPを確認
```
ip a | grep "inet "
```
を入力しEnter。

すると以下のような結果ができました。（中身は適当な数字です）
```
inet 127.0.0.1/8 scope host lo
inet 192.168.1.100/24 brd 192.168.1.255 scope global eth0
```
このうち、`127.0.0.1` はローカルホスト（サーバー自身のみアクセス可能）なので無視して、`192.168.x.x`のようなローカルIPを確認すると良いらしい。
（って知り合い教えてもらいました。なぜかはあまり理解できてないのでこれから勉強します💦）
このIPをブラウザのURLバーに入力してアクセスする。

```
curl -I http://localhost
```
を入力して、
```
HTTP/1.1 200 OK
Date: ...
Server: Apache/...
```
のような出力が出ればApacheが正常に動いてるので、URLにアクセスしてApacheのデフォルトページが表示されるかを確認します。

#### 結論
やったこと②でローカルIPを確認すればよさそう！
ってことでこのトラブルは解消

### ここでトラブル２
ブラウザ自体を開くことはできましたが、画面に
```
Not Found 
The requested URL was not found on this server.

Apache/2.4.52 (Ubuntu) Server at 172.30.163.23 Port 80
```
と表示されてしまいました。

調べてみると、どうやらApacheは動いているけど表示するファイルが見つからないという状態のようです。

#### やったこと
以下のコマンドでApacheの設定ファイルを開いてみました。
```
sudo nano /etc/apache2/sites-enabled/000-default.conf
```
nanoエディタなるものが開くので、一度`Ctrl + X`で抜けました。

```
ls -l /var/www/html
```
を入力し、`index.html`があればOK。

ここでApacheを以下のコマンドで再起動して、
```
sudo systemctl restart apache2
```

もう一度ローカルIPにアクセスしたら、
**ブラウザ上でApacheのデフォルトページが表示**されました！

#### 結論
Apacheを再起動したらよかったっぽいです。
原因はよくわからずです、、、

ようやく次のステップに進めます。

## HTMLファイルの作成
①以下のコマンドを入力
```
$ cd /var/www/html
$ ls
```
ここにindex.htmlがあり、これがApacheデフォルトページにあたるそう。

②新しくHTMLファイルを作成
```
$ sudo touch test.html
(ファイル名は何でもOK)
```
次に以下を入力
```
$ sudo nano test.html
```

nanoエディタが開くので、ここにHTMLを記述。
私は以下のように記述しました（どっかにあったのを適当にコピペしただけ）
```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title></title>
</head>
<body>
    <h1>Hello world</h1>
</body>
</html>
```
保存した後、ブラウザでローカルIPアドレスにアクセス。
ブラウザが表示されたら成功！🌟
ネットワーク入門：WINSとDNSの違いとは？ いま知っておきたい名前解決の基礎について振り返ってみた

## はじめに  
ネットワーク環境の変化とともに、かつて広く使われていた技術の役割も変わっていきます。  
**WINS（Windows Internet Name Service）サーバ** は、Windows ネットワークにおいて **NetBIOS 名の名前解決** を担ってきた重要な技術でした。  

:::note info
**しかし、現在では **DNS（Domain Name System）が主流** となり、WINS の利用は減少しています。**
:::

本記事では、**WINS サーバの基本的な仕組みや役割、設定方法、そして現在の代替手段** について解説します。 

## 書こうと思ったきっかけ  
最近、**レガシーな Windows ネットワーク環境を管理** する機会があり、  
**WINS サーバがまだ一部のシステムで利用されている** ことを改めて認識しました。  

:::note warn
***特に、**古いシステムの保守や移行を検討する際、WINS と DNS の違いを正しく理解すること** は重要です。***
:::

**現代のネットワーク環境において WINS がどのような位置づけにあるのか、また、今後どのように対応すべきかを整理** するために、この内容を書きました。  

## WINSサーバとは

WINS（Windows Internet Name Service）サーバは、Windows環境においてNetBIOS名をIPアドレスに解決するための名前解決サービスです。

主にWindows NT時代に活用されていましたが、現在ではDNS（Domain Name System）が広く利用されているため、使用機会は減少しています。

## WINSサーバの役割

1. **NetBIOS名の解決**
   - WindowsネットワークでNetBIOS名を使用してコンピュータを識別する際、WINSサーバが名前とIPアドレスの対応関係を管理します。
   
2. **動的な登録と解決**
   - DHCP環境で動的に変わるIPアドレスを管理するのに適しており、クライアントは自身のNetBIOS名とIPアドレスをWINSサーバに登録します。

3. **ネットワークトラフィックの削減**
   - WINSサーバを導入することで、NetBIOSブロードキャストによる名前解決のトラフィックを削減できます。

## WINSとDNSの違い

| 項目 | WINS | DNS |
|------|------|------|
| 解決対象 | NetBIOS名 | ホスト名、FQDN |
| プロトコル | NetBIOS | TCP/IP（主にUDP/TCP 53番）|
| 動的更新 | 可能 | 可能（DDNSを利用）|
| 廃止の流れ | あり | 主流 |

## WINSの構成要素

1. **WINSサーバ**：名前解決情報を保持し、クライアントの登録・照会を処理する。
2. **WINSクライアント**：自身のNetBIOS名をWINSサーバに登録し、他のクライアントのIPアドレスを問い合わせる。
3. **レプリケーション**：複数のWINSサーバ間で情報を同期する仕組み。

## WINSの設定方法（Windows Server）

1. **WINSのインストール**
   - 「役割と機能の追加」からWINS機能を有効化
   - サーバーマネージャーからWINSサーバを設定

2. **クライアントの設定**
   - ネットワークアダプターのプロパティでWINSサーバのIPアドレスを指定

3. **レプリケーションの設定**
   - 複数のWINSサーバ間でデータを同期する設定を行う

## WINSの廃止と代替手段

現在ではWINSの利用は推奨されておらず、以下の手法に移行することが一般的です。

- **DNSへの統合**：Active Directory環境ではDNSが標準で使用されるため、DNSへ統合する。
- **NetBIOS over TCP/IPの無効化**：新しいWindows環境ではNetBIOSの使用を避け、SMB over TCP/IP（ポート445）を使用する。
- **mDNSやLLMNRの活用**：ローカルネットワークでの名前解決にBonjour（Apple）やLink-Local Multicast Name Resolution（Windows）を利用する。

## まとめ

WINSサーバはかつてWindows環境において重要な役割を果たしていましたが、現在ではDNSへの移行が進んでいます。

既存のシステムでWINSが使われている場合、DNSや他の名前解決手法への移行を検討することが推奨されます。
StableDiffusion WebUIでPython仮想環境を使用する

## 概要
Stable Diffusion WebUI AUTOMATIC1111(以下SD WebUI)をローカルにインストールしようと思ったら、Python3.10.6が推奨らしい。
でも既に他のバージョンのPythonを使っているので、環境がごちゃごちゃになるのは嫌だ…
そんな時、Python仮想環境が便利です。
## 環境
OS : Windows11
CPU : Core i5-12400
GPU : GeForce RTX 3060
##  Pythonをインストールする
もちろんバージョンは3.10.6。
公式サイトから Windows installer(64-bit) をダウンロードし実行する。

https://www.python.org/downloads/release/python-3106/

何も考えずNextを押して行けばOK。
「Add Python 3.10 to PATH」を**チェックしない**ようにする。
（チェックすると現在のPython環境が上書きされるので）

私の場合は以下のフォルダにインストールされました。
C:\Users\ユーザー名\AppData\Local\Programs\Python\Python310
このパスを忘れずメモっておきましょう（後で使います）。
## Gitをインストールする
既にインストール済の方は飛ばして下さい。
ダウンロードページの Click here to download と書かれたリンクをクリックして最新版をダウンロードし実行する。

https://git-scm.com/downloads/win

何も考えずNextを押して行けばOK。
## Stable Diffusion web UIをインストールする
### インストールする場所を決める
SD WebUIをインストールする場所を決めます。
ファイルパスが長くならないよう浅目の階層が便利です。

今回は例として、Cドライブ直下に sd というフォルダを作ります。
### インストール
コマンドプロンプトを開き、先ほど作ったフォルダ C:\sd へ移動し、以下のコマンドを実行します。
~~~
git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git
~~~
## Python仮想環境の作成
ここからが本番です。
SD WebUIのインストールが終わったら、続けて以下のコマンドを実行します。
最初にメモっておいたPythonのインストール先をここで使います。
~~~
C:\Users\ユーザー名\AppData\Local\Programs\Python\Python310 -m venv C:\sd\venv
~~~
これによって指定したフォルダに仮想環境が作成されます。
今回は C:\sd\venv フォルダの中にPython3.10.6の仮想環境を作りました。
## webui-user.batの編集
SD WebUI が仮想環境で実行されるようにバッチファイルを編集します。
C:\sd\stable-diffusion-webui フォルダにある webui-user.bat をテキストエディタで開きます。
これを下のように変更します（補足：-は削除、+は追加）。
~~~diff:webui-user.bat
@echo off

set PYTHON=
set GIT=
- set VENV_DIR=
+ set VENV_DIR=C:\SD\venv
set COMMANDLINE_ARGS=

+ call %VENV_DIR%\Scripts\activate
call webui.bat
~~~
やっている事は、仮想環境のフォルダを指定し SD WebUI を起動する前に activate で有効化しています。
## SD WebUI を起動
テキストエディタを閉じ、 webui-user.bat を実行します。
初回起動なので、必要なファイルのダウンロードが行われます。
何も入力せず見てるだけでOKですが、かなり時間がかかるので（私の環境では10分ほど）気長に待ちましょう。

自動的にブラウザが立ち上がれば完了です。
後は良き画像生成ライフを！
【ITパスポート / 基本情報技術者 / 応用情報技術者】資格取得のためにやったこと＆これからやること

# はじめに
資格より実務だとは思うのですが、not情報系学生として少しは基礎固めになればと思い日々勉強しております！

# ITパスポート（取得）
<dl>
  <dt>学習開始時期</dt>
  <dd>2024年2月下旬</dd>
  <dt>受験時期</dt>
  <dd>2024年4月5日</dd>
  <dt>学習時間</dt>
  <dd>約30h（電車移動中に勉強して、1日約1hで1カ月の計算）</dd>
  <dt>学習教材</dt>
  <dd>Youtubeチャンネル。「ITパスポート 絶対合格の講座」を1周したのち、「みみスタ」の暗記動画を周回。</dd>
  <dt>得点</dt>
  <dd>ストラテジ系：640点、マネジメント系：825点、テクノロジ系：805点</dd>
  <dt>所感</dt>
  <dd>英単語の暗記がメイン。みみスタに大変お世話になった。</dd>
</dl>

:::note info
使った教材はこちら
- [ITパスポート 絶対合格の講座](https://www.youtube.com/@itpassport)
- [みみスタ](https://www.youtube.com/@mimi_study/videos)
:::

# 基本情報技術者（取得）
<dl>
  <dt>学習開始時期</dt>
  <dd>2024年7月下旬</dd>
  <dt>受験時期</dt>
  <dd>2024年9月17日</dd>
  <dt>学習時間</dt>
  <dd>約120h（電車移動中＋家で勉強していて、1日約2hで2カ月の計算）</dd>
  <dt>学習教材</dt>
  <dd>教科書＋Youtubeチャンネル＋過去問道場＋IPA過去問。教科書とYoutubeチャンネルを1周したのち、科目Aは過去問道場、科目BはIPAの過去問で対策。</dd>
  <dt>得点</dt>
  <dd>科目A評価点：730点、科目B評価点：845点</dd>
  <dt>所感</dt>
  <dd>過去問道場をトータル300問ぐらいしかしなかったので、本番で初見問題が多くてきつかった。もっと多めにやっておくべきだったと感じる。</dd>
</dl>

:::note info
使った教材はこちら
- [イメージ＆クレバー方式でよくわかる かやのき先生の基本情報技術者教室](https://gihyo.jp/book/2023/978-4-297-13827-1)
- [【基本情報技術者試験YouTuber】すー](https://www.youtube.com/@mimi_study/videos)
- [過去問道場](https://www.fe-siken.com/fekakomon.php)
- [IPA過去問](https://www.ipa.go.jp/shiken/mondai-kaiotu/sg_fe/koukai/index.html)
:::

# 応用情報技術者（勉強中）
<dl>
  <dt>学習開始時期</dt>
  <dd>2025年3月上旬</dd>
  <dt>受験時期</dt>
  <dd>2025年4月20日</dd>
  <dt>学習時間</dt>
  <dd>--</dd>
  <dt>学習教材</dt>
  <dd>--</dd>
  <dt>得点</dt>
  <dd>--</dd>
  <dt>所感</dt>
  <dd>--</dd>
</dl>

:::note info
使った教材はこちら
- []()
:::

# おわりに
勉強のことで詰まったらなんでも質問してくださいね！（私も全然わかってませんけど！
AWS入門： マネジメントコンソール上から手動で停止も起動もできなかったため、AWS CLIを使用して強制的に停止してみた

## **はじめに**
AWS で EC2 インスタンスを管理していると、マネジメントコンソール上でインスタンスの起動や停止ができなくなることがあります。

今回は、そのような状況で AWS CLI を使ってインスタンスを停止し、状態を確認する方法をまとめました。

## **書こうと思ったきっかけ**
EC2 インスタンスがマネジメントコンソール上から **起動も停止もできず** に困った経験がありました。

その際に AWS CLI を利用して解決したため、同じ問題に直面した際の参考になればと思い、この記事を書きました。

## **1. EC2 インスタンスの停止**
EC2 インスタンスを停止するには、以下の AWS CLI コマンドを使用します。

```sh
aws ec2 stop-instances --instance-ids <インスタンスID> --force
```

**例:**
```sh
aws ec2 stop-instances --instance-ids i-xxx --force
```

**出力結果:**
```json
{
    "StoppingInstances": [
        {
            "InstanceId": "i-xxx",
            "CurrentState": {
                "Code": 64,
                "Name": "stopping"
            },
            "PreviousState": {
                "Code": 64,
                "Name": "stopping"
            }
        }
    ]
}
```

この出力は、インスタンスが停止処理中 (`stopping`) であることを示しています。

## **2. インスタンスの状態を確認する**
インスタンスが完全に停止されたかどうかを確認するには、以下のコマンドを実行します。

```sh
aws ec2 describe-instances --instance-ids <インスタンスID> --query 'Reservations[].Instances[].State'
```

**例:**
```sh
aws ec2 describe-instances --instance-ids i-xxx --query 'Reservations[].Instances[].State'
```

**出力結果:**
```json
[
    {
        "Code": 80,
        "Name": "stopped"
    }
]
```

この結果が "Name": "stopped" であれば、インスタンスは正常に停止されています。

## **3. 次のアクション**
### **(1) 再起動する場合**
インスタンスを再起動するには、以下のコマンドを実行します。

```sh
aws ec2 start-instances --instance-ids <インスタンスID>
```

**例:**
```sh
aws ec2 start-instances --instance-ids i-xxx
```

このコマンドを実行すると、インスタンスの状態が `pending` から `running` へと変わります。

### **(2) 完全に削除（終了）する場合**
インスタンスを完全に削除し、料金の発生を止めるには、以下のコマンドを実行します。

```sh
aws ec2 terminate-instances --instance-ids <インスタンスID>
```

**例:**
```sh
aws ec2 terminate-instances --instance-ids i-xxx
```

**注意:** `terminate` すると、インスタンスが完全に削除され、元に戻せません。

### **(3) 停止したまま保持する場合**
- `stopped` 状態では、EC2 のインスタンス料金は発生しませんが、EBS（ストレージ）の料金は発生する点に注意。
- 必要なときに `start-instances` コマンドで再起動できます。

## **まとめ**
- EC2 インスタンスの停止は `stop-instances` コマンドで可能
- `describe-instances` で状態を確認し、`stopped` になっていれば停止完了
- 再起動したい場合は `start-instances`、完全に削除したい場合は `terminate-instances` を使用
- `stopped` の状態ではインスタンス料金は発生しないが、EBS の料金はかかるので注意

これらのコマンドを活用して、AWS EC2 インスタンスの管理を適切に行いましょう！

## 参考文献

https://dev.classmethod.jp/articles/tsnote-ec2-stop-force-001/
ラズベリーパイ5でDCモーターの制御プログラム

１．概要
ラズベリーパイ5とDRV8835モータドライバを接続してGPIOを使ってモーターを回転するプログラムの解説をする。
プログラムの特徴やポイントに加えて、利用するGPIOピンを変更したときの変更などを説明する。
ラズベリーパイ４でも動作するはずです。

２．プログラムの特徴
初心者でも理解しやすいように、単純なプログラム構成とします。
以下の通りラズベリーパイ５のGPIO25とGPIO24を使いモーターを制御します。

![MotorControl.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1891553/59aef6c7-9f03-af41-098a-c1ecd97829ca.jpeg)

プログラムの終了時、出力をOFFにして、誤動作を防止します。

３．プログラム本体
```python:MotorControl.py
from time import sleep
from gpiozero import OutputDevice

MOTOR1 = 25  # GPIO25
MOTOR2 = 24  # GPIO24

def device_cleanup(device1, device2):
    device1.close()
    device2.close()

motor_pin_1 = OutputDevice(MOTOR1)
motor_pin_2 = OutputDevice(MOTOR2)

print(f'Start GPIO motor control')

try:
    while True:
        motor_pin_1.on()
        motor_pin_2.off()
        sleep(0.5)
except KeyboardInterrupt:
    pass

motor_pin_1.off()
motor_pin_2.off()
device_cleanup(motor_pin_1, motor_pin_2)

print(f'Finished GPIO motor control')
```
４．プログラムのポイント
上記のプログラムの内容を解説します。

(1) GPIOピンの定義
 GPIOピンの番号を設定
 
    MOTOR1 = 25  # モータ用ピン1 (GPIO25)
    MOTOR2 = 24  # モータ用ピン2 (GPIO24)

DRV8835モータドライバのモータA出力に接続する２つのピン番号を設定します。

(2) GPIOピンの初期化
 ピンの準備

    motor_pin_1 = OutputDevice(MOTOR1)
    motor_pin_2 = OutputDevice(MOTOR2)

OutputDeviceを使ってGPIOピンを制御可能な状態に設定します。

(3) モータを回転させるループ処理
　モータを動かすメイン部分


    while True:
        motor_pin_1.on()  # モーターを回転する
        motor_pin_2.off() 
        sleep(0.5)  # 0.5秒遅延


GPIO25をONにして、GPIO24をOFFにするとモーターが回転する。
次に出力するまで、0.5秒の遅延をいれる。
Ctrl＋C（CTRLキーを押しながら、Cを押す）が押されるまで、プログラムを繰り返す。

(4) 終了処理
　プログラムを終了するため、モーターを停止して、リソースを解放する


    motor_pin_1.off()
    motor_pin_2.off()
    device_cleanup(motor_pin_1, motor_pin_2)

ピンをOFFにし、クリーンアップ処理でリソースを解放する。

５．変更箇所の解説
ピン番号を変更する場合は、以下を変更する。

MOTOR1 = <新しいGPIO番号>
MOTOR2 = <新しいGPIO番号>

このプログラムは、モータを制御するモータA出力へラズベリーパイ５のGPIO24とGPIO25を接続している。
接続先を変更する場合は、MOTOR1とMOTOR2を変更する。

他にもラズベリーパイを使ったIoTに利用できるプログラムの説明を書いていきます。
一覧は、ここを見てください。
スイッチの設定でハイフンで省略されているVLAN番号を省略しない形にして見やすくするスクリプト

# なぜ作ったか？
ネットワーク機器でVLANの設定をする際に、"3-10,13,17-22" のような形式で書かれているが、これをほどきたくなる瞬間がよくあるからw

# スクリプト本体

```python:vlan-split.py
#!/usr/local/bin/python3

import sys
import argparse

def expand_ranges(input_string):
    # 結果を格納するリスト
    result = []
    # カンマで区切って処理
    for part in input_string.split(','):
        # 範囲のチェック
        if '-' in part:
            start, end = map(int, part.split('-'))
            # 範囲内の数字を追加
            result.extend(range(start, end + 1))
        else:
            # 単一の数字を追加
            result.append(int(part))
    return result

if __name__ == "__main__":
    # 引数パーサーの設定
    parser = argparse.ArgumentParser(description="Expand ranges in input string")
    parser.add_argument("-n", action="store_true", help="Use newline instead of comma as separator")
    args = parser.parse_args()

    # 標準入力からデータを取得
    input_string = sys.stdin.read().strip()
    expanded_list = expand_ranges(input_string)

    # 出力を選択
    separator = "\n" if args.n else ","
    print(separator.join(map(str, expanded_list)))
```
# 実行例
```terminal:オプションなし
% echo "3-5,10" | vlan-split.py
3,4,5,10
```
```terminal:-n オプション
% echo "3-5,10" | vlan-split.py -n
3
4
5
10
%
```
##
【Golnag】gRPC zapの基本とLogの出し分け

## Zapとは？
構造化メッセージを自由に構築できる、高速なロギングライブラリ
gRPCにloggerをセットする用の関数とかも用意されています。

## 基本的な使い方
loggerを生成して、logを出力する
```
logger, _ := zap.NewProduction()
logger.Info("test")
```

## interceptorを用いてgRPCにLoggerを設定するには？
gRPCのサーバを作成する際のオプションとして、interceptor(middleware的なもの)を使用すれば、hundlerの前後に任意の処理を挟むことができます。
grpc_zapというzapのloggerをgRPCにセットする用のパッケージも用意されているのでそれを使用するだけで、loggerを設定できます。
```
server := grpc.NewServer(
    grpc.UnaryInterceptor(grpc_zap.UnaryServerInterceptor(logger)),
)
```

## 出力されるログのラベルを変更するには？
configを独自に設定して、それをもとにloggerをBuildしてやればいい。
```
myConfig := zapcore.EncoderConfig{
    TimeKey:        "xxxx",
    LevelKey:       "xxxx",
    NameKey:        "xxxx",
    CallerKey:      "xxxx",
    MessageKey:     "xxxx",
    StacktraceKey:  "xxxx",
    EncodeLevel:    xxxx,
    EncodeTime:     xxxx,
    EncodeDuration: xxxx,
    EncodeCaller:   xxxx,
}
 
logger, err :=  myConfig.Build()
```

## ログのrotateを設定するには？
### zapCoreを生成する際にrotateの設定が可能
Filename : ログの吐き出し場所
MaxSize : ログの最大サイズ（MB）。デフォルトは100MB
MaxBackups : 残しておくログファイル数
MaxAge : 残しておくログファイルの日数
Compress : rotateするときに圧縮するかどうか

```
writeSyncer := zapcore.AddSync(&lumberjack.Logger{
    Filename:   /test.log,
    MaxSize:    100,
    MaxBackups: 5,
    MaxAge:     30,
    Compress:   true,
})
core := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(infoFileWriteSyncer), debug)
logger := zap.New(core)
```

## ログレベルによって出力先を出し分けするには？
zapCoreを出力先分作成すればよい
ConfigのOutputPathsとErrorOutputPathsはレベルごとに出力先を決めるためのもの、
ではないので注意。紛らわしい

```
// ログレベルが低い設定を作成。今回はdebug-infoまでを設定
low := zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
    return lev >= zap.DebugLevel && lev <= zap.InfoLevel
}) 
 
// ログレベルが高い設定を作成。今回はwarn以上を設定
high := zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
    return lev >= zap.WarnLevel
})
 
// それぞれのzapCoreを作成する
lowCore := zapcore.NewCore(Encoder, WriteSyncer,  low)
highCore := zapcore.NewCore(Encoder, WriteSyncer,  high)
 
// coreの配列を作成する
var coreArr []zapcore.Core
coreArr = append(coreArr, lowCore)
coreArr = append(coreArr, highCore)
 
// loggerを作る
logger := zap.New(zapcore.NewTee(coreArr...)
```
Win スクール「【前半】 Linux サーバー構築 (Ubuntu)」受講所感

# Win スクール「【前半】 Linux サーバー構築 (Ubuntu)」受講所感

https://www.winschool.jp/guidance/program/linux_server.html

## はじめに

2025 年 4 月から社会人（エンジニア）になる大学院生です。

今回、[Win スクール](https://www.winschool.jp/)の「[Linux サーバー構築 (Ubuntu)](https://www.winschool.jp/guidance/program/linux_server.html)」の前半を受講しましたので，その所感を書かせていただきます。

## Win スクールとは

:::note info
[ホームページ](https://www.winschool.jp/)の情報を元に情報を抜粋して書いています。詳細は、[ホームページ](https://www.winschool.jp/)をご確認してください。
:::

https://www.winschool.jp/

### Win スクールの講座

https://www.winschool.jp/guidance/

Win スクールでは、講座数が 300 講座以上展開されています。

- [Microsoft Office・パソコン資格](https://www.winschool.jp/guidance/business/)
- [WEB デザイン・WEB プログラミング](https://www.winschool.jp/guidance/web/)
- [グラフィックデザイン・映像デザイン](https://www.winschool.jp/guidance/design/)
- [CAD（機械／建築）3DCAD・インテリア](https://www.winschool.jp/guidance/cad/)
- [プログラミング・ネットワーク](https://www.winschool.jp/guidance/program/)
- [DX・データ分析・業務効率化](https://www.winschool.jp/guidance/dx/)

---

https://www.winschool.jp/recareer/

「[リスキリングを通じたキャリアアップ支援事業](https://careerup.reskilling.go.jp/)」制度対象の講座もあります。

### Win スクールの特徴

- 教室でもオンラインでも、プロの講師が個別で指導
- 少人数の教室だから質問しやすく、初心者も安心
- 数多くの企業研修にも選ばれる、豊富なカリキュラム
- 就職時や卒業後も心強い、充実のフォローアップ体制

### 教室

https://www.winschool.jp/map/

全国約 50 校あります。また、オンラインでの学習も可能です。

## 講座の内容

https://www.winschool.jp/guidance/program/linux_server.html

講座名：【前半】 Linux サーバー構築 (Ubuntu)
対象：サーバーエンジニアやネットワークエンジニアを目指す方・Linux を基礎から学習したい方・Web サーバーを構築したい方
回数・時間：10 回（1 回あたり 90 分）
内容：基本的なコマンド操作・テキストエディタの使い方・テキスト処理・ネットワークの設定と管理・ユーザ管理・ファイルとプロセスの管理

## 所感

### 通学受講 or オンライン受講

私は、この講座を通学受講しました。
通学を選択した理由は、以下の通りです。

- 家での学習より集中できる
- 大学への登下校するついでに Win スクールで学習できる

### 学習の流れ

Win スクールでの勉強は、自分のペースで進めやすいと特に感じました。私は Linux の基本的なコマンド（例えば、`ls` や `touch sample.txt`）は知っていたので、そこの単元は比較的早いペースで学習を進めました。ただ、知らないオプションは多くありましたので、それぞれのオプションを使って、実行は行いました。最初の方の単元は早いペースで進めたので、最初の方は予定表より早く進めました。一方、「ネットワークの設定と管理」の単元では、（[基本情報技術者試験](https://www.ipa.go.jp/shiken/kubun/fe.html)に合格しているので、多少の知識はあっても実際に行ったことがないため）中々理解できないところもあり、遅いペースで進めました。

私は基本的には、週 2 回通学していました。Win スクールは毎回日時を指定できるので、柔軟に受講スケジュールを組むことができました。Win スクールは、1 日に 2 回受講することもできます。

授業の最終回には、テストがありました。

### 教室の雰囲気

わからない時は、[講師](https://www.winschool.jp/teacher/)の方に質問を積極的にしました。私が通学した教室には、常に 2 ~ 3 人の講師がいました。

## おわりに

今回、[Win スクール](https://www.winschool.jp/)の「 Linux サーバー構築 (Ubuntu)」の前半を受講した所感を書かせていただきました。

この記事がパソコン教室・パソコンスクールの選択で迷っている人の参考になれば幸いです。
Outlook の会議室を取得する方法いろいろ

# はじめに

ごきげんよう、百合宮桜です！
今日はみんな大好き対面ミーティングで重要な「会議室」についてお話しします。

Power Automate で「会議室」を検索すると、以下の3つのアクションが出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/431071ef-b9d1-461b-aaf3-f73d12741894.png)

これは Power Apps でも使うことができます

| Power Automate | Power Apps |
|:-:|:-:|
| 会議室の取得  | Office365Outlook.GetRoomsV2()  |
| 会議室の一覧の取得  | Office365Outlook.GetRoomListsV2()  |
| 会議室の一覧から会議室を取得  | Office365Outlook.GetRoomsInRoomListV2()  |

それぞれ役割が異なります。

# 会議室の取得

会議室をリスト形式で取得します。ただ取得数の上限が100件なので、Outlook に登録されている会議室の合計数が100件以上の場合は100件までしか取得できません。

【Power Automate での取得結果】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/87c1f611-bab4-4eef-aab5-94530b7ac939.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/b50fe580-90c6-4d9c-b76b-8f43b2298b5d.png)

【Power Apps での取得結果】

```
Office365Outlook.GetRoomsV2().value
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/981e832d-f668-4462-b7c7-9a8cb6b6682b.png)

# 会議室の一覧の取得

会議室の一覧とは意味あるカテゴリーで会議室をリスト形式にわけたものです。
IT管理部門のように Outlook の管理権限がある人が設定できます。
この「会議室の一覧」が設定されていると、本アクションで会議室の一覧が取得できます。

【Power Automate での取得結果】

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/4d797f8e-1ec8-427b-b323-fdb8d74fd327.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/3e2e2c9a-46e9-4d68-a7ae-5718149baf18.png)



【Power Apps での取得結果】

```
Office365Outlook.GetRoomListsV2().value
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/99aed496-af23-41de-af81-dde0ee95d95f.png)

この会議室の一覧が登録されていると、次の「会議室の一覧から会議室を取得」アクションが利用できるようになります・

# 会議室の一覧から会議室を取得

会議室の一覧を指定して、その一覧から会議室を取得する方法です。

【Power Automate での取得結果】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/2b267282-92b2-447f-806f-875dc3d9e455.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/ca2ba098-c8d8-4480-b081-bf9390f3b4fa.png)

結果は配列でかえります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/40d7f5dc-817d-429b-b4f1-bd4574ec5789.png)

【Power Apps での取得結果】

```
Office365Outlook.GetRoomsInRoomListV2("会議室一覧のメールアドレス").value
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/6b024c3f-8da7-461c-bb22-9336818dfaa1.png)

会議室一覧のメールアドレスは「会議室の一覧の取得」で取得することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/d58b02ff-7ba8-4523-8aff-247ae0e7d26b.png)

# おわりに

うまく使えば、会議室の取得上限である 100 件を回避しつつ、会議室を動的に取得できます。各アクションを上手に使い分けてくださいね(≧▽≦)
それではごきげんよう♪
最強のチームを作る！成功するチームビルディングの極意

## はじめに
チームビルディングは、単なる「人を集めること」ではなく、目的を達成するために個々の力を最大限に引き出し、相互に補完し合う環境を作ることが重要です。本記事では、強いチームを作るための具体的なステップや成功事例を交えて詳しく解説します。

---

## 1. 強いチームの特徴
### 1-1. 明確なビジョンと目標
チームメンバーが同じ方向を向いて進むためには、共通のビジョンと目標が必要です。
- **ビジョン**：チームの存在意義や目指す方向性
- **目標**：短期・中期・長期の具体的な達成基準
- **役割分担**：各メンバーが自分の強みを活かせるような役割設計

### 1-2. 信頼関係の構築
信頼関係は強いチームの土台です。信頼を築くために、以下の点を意識しましょう。
- **オープンなコミュニケーション**：意見を言いやすい環境を作る
- **役割と責任の明確化**：各メンバーが自分の役割を理解し、責任を持つ
- **フィードバックの文化**：建設的なフィードバックを行うことで成長を促す
- **チームビルディングのアクティビティ**：定期的なワークショップや交流会を実施する

### 1-3. 多様性と補完性
メンバーのスキルや経験の多様性が、チームの強さを生みます。
- 異なる専門性を持つメンバーを集める
- 互いの強みを活かし、弱点を補い合う
- 文化の違いを尊重し、相互理解を深める

---

## 2. 強いチームを作るためのステップ
### 2-1. 適切なメンバーの選定
チームの目的に応じた適切なメンバーを選ぶことが重要です。
- スキルだけでなく、価値観やチームへの適合性も考慮
- 必要に応じてロール（役割）を調整
- 採用・異動の際にチームのバランスを見直す

### 2-2. コミュニケーションの強化
コミュニケーションの質がチームの成果を左右します。
- **定期的なミーティング**：進捗共有と課題解決の場を設ける
- **オンラインツールの活用**：SlackやNotionなどのツールを活用し、円滑な情報共有を行う
- **心理的安全性の確保**：失敗を恐れず意見を言える環境を作る
- **1on1ミーティングの実施**：個々の悩みや課題に寄り添う

### 2-3. モチベーションの維持と向上
モチベーションを高めるためには、適切な評価と成長機会が重要です。
- **達成感を得られる仕組み**（マイルストーン設定、成果の可視化）
- **学習と成長の機会を提供**（勉強会、メンター制度の導入）
- **インセンティブの活用**（報酬・表彰制度）

---

## 3. 具体的な成功事例
### 3-1. Googleの「心理的安全性」
Googleのプロジェクト・アリストテレスでは、「心理的安全性」がチームの成功に不可欠な要素であることが判明しました。メンバーが自由に意見を言える環境が、イノベーションやパフォーマンス向上につながります。

### 3-2. アジャイル開発チームの成功例
アジャイル開発を採用するチームでは、スプリント（短期間の開発サイクル）ごとに成果を確認し、迅速なフィードバックを行うことで、チームの適応力と効率が向上します。

### 3-3. Netflixの「自由と責任」文化
Netflixでは、社員に大きな裁量権を与え、自由な働き方を推奨することで高いパフォーマンスを発揮する文化を築いています。厳しいルールよりも、信頼関係に基づいた環境作りが重要視されています。

---

## まとめ
強いチームを作るには、**ビジョンの共有、信頼関係の構築、多様性の活用、効果的なコミュニケーション**が不可欠です。また、適切なモチベーション管理や、成功事例を参考にした施策も重要になります。

継続的な改善を行いながら、チームの成長を促していきましょう。

**あなたのチームでは、どんな取り組みをしていますか？** ぜひコメントで共有してください！
Stream Deckでbatファイルを実行するアクションを追加する

[Stream Deck](https://www.elgato.com/jp/ja/p/stream-deck-mk2-black) でWindowsの.batファイルを実行するボタンを設定する方法のメモです。

「システム」> 「開く」アクションの設定項目の「App/ファイル」に以下を入力すれば完了です。

```bat
cmd.exe /c "バッチファイル.bat"
```
アクションを実行するとコマンドプロンプト画面が起動して指定したバッチが実行されます。

## 入力例

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123353/0d43a8d6-05e0-4fa5-bc64-860f04b53970.png)

## NOTE

`cmd.exe /c`の部分を書かずにバッチファイルパスを入力するだけでも実行できますが、そのときはコマンドプロンプト画面が開かれずバックグラウンドで実行されます。
私も実際に試したところタスクマネージャ上では確かにプロセスが起動したことを確認できました。
しかしその試したバッチで意図した処理は正常に行われませんでした。どうやらファイルのパスに依存する処理などはうまく動かないようです。
上記のように`cmd.exe /c`の引数に渡すようにすると正常に実行することができました。

## 参考
https://www.reddit.com/r/ElgatoGaming/comments/82iiyy/trying_to_run_a_bat_file_with_stream_deck/?rdt=38980
「またやっちゃった！」.ts ファイルで JSX が使えない罠と私の自戒録

React と TypeScript を使った開発をしていると、一度は遭遇する問題があります。

それは「あれ？なんでエラーになるんだろう？」と首をかしげながら、ふと気づく `.ts` と `.tsx` の違い。（私だけ？？？🥹）

この記事は、何度も同じミスを繰り返してしまう私自身への自戒の意味も込めて書いています。

# またやってしまった！よくある状況
いつものように新しいコンポーネントを作成しようと思い、ファイルを作成...

```typescript: Header.ts
// Header.ts  <- 気づきましたか？
import React from 'react';

const Header = () => {
  return (
    <div>
      <h1>Welcome to my website</h1>
    </div>
  );
};

export default Header;
```
保存して...そして待っているのは赤い波線とエラーメッセージ

```txt
error TS17004: Cannot use JSX unless the '--jsx' flag is provided.
```

あるいは

```txt
error TS1005: '<' expected.
```
「あ、また .ts で作っちゃった...」

# なぜ起こるのか？シンプルな説明
React と TypeScript の世界では、拡張子に明確な役割分担があります。

- `.ts` - 普通の TypeScript ファイル（JSX は使えない）
- `.tsx` - JSX が使える TypeScript ファイル

これは単なる慣習ではなく、TypeScript コンパイラが異なる方法でこれらのファイルを処理するためです。

# `<Header />` vs `Header({})` の謎
面白いことに、`.ts` ファイル内では `<Header />` というJSX記法は使えませんが、同じコンポーネントを `Header({})` という関数呼び出しの形で使うことはできます。

なぜでしょう？簡単に言えば、
- `<Header />` は特殊な JSX 構文で、`.tsx` ファイルでのみ解釈できる
- `Header({})` は普通の関数呼び出しなので、どのファイルでも問題なく動作する
からです。

```typescript:utils.ts
import { Header } from './components/Header';

// エラー: .tsファイルではJSX構文は使えない
const jsx = <Header title="Hello" />;

// OK: 関数呼び出しは普通に動作する
const func = Header({ title: "Hello" });
```

# 解決方法
問題に気づいたら、解決法はいくつかあります。

### 1. ファイル拡張子を `.tsx` に変更する（推奨）
最も簡単で適切な解決方法は、JSX を含むファイルの拡張子を `.ts` から `.tsx` に変更することです。

```txt
Header.ts → Header.tsx
```

これにより、TypeScript コンパイラは正しく JSX 構文を解析できるようになります。

### 2. tsconfig.json で JSX サポートを設定する
tsconfig.json で JSX のサポートを有効にすることも可能ですが、これはプロジェクト全体に影響します。

```yaml
{
  "compilerOptions": {
    "jsx": "react",
    // その他の設定...
  }
}
```

### 3. `React.createElement` を直接使用する
JSX はコンパイル時に `React.createElement` の呼び出しに変換されます。JSX を使用せずに直接これを記述することもできますが、可読性が大幅に低下します。

```typescript:Header.ts

import React from 'react';

const Header = () => {
  return React.createElement(
    'div', 
    null, 
    React.createElement('h1', null, 'Welcome to my website')
  );
};

export default Header;
```

# まとめ：私の自戒メモ
TypeScript と React を使う限り、この問題は付きまとう可能性があります。

気づかずに何度も同じミスを繰り返さないよう、「ファイルの拡張子に注意する」ことを自分自身への戒めにします...😣

この単純なルールを忘れないことで、「なんでJSXが使えないんだ？」とデバッグに時間を浪費することもなくなるでしょう。

あなたも私と同じミスで悩んでいたら、今日からは ファイルの拡張子 を意識して、快適な React + TypeScript 開発を楽しみましょう！
LLMの推論APIにおけるレイテンシーとは？



LLM（大規模言語モデル）の推論APIでは、**レイテンシー（応答時間）** が重要な指標となります。特に、リアルタイム応答が求められるアプリケーション（チャットボット、音声アシスタント、検索エンジンなど）では、レイテンシーを最適化することが不可欠です。

本記事では、**p95レイテンシーとは何か？遅いと判断される基準、改善方法** について詳しく解説します。

---

## **1. p95レイテンシーとは？**

### **レイテンシーの基本概念**
レイテンシーとは、リクエストが送信されてからレスポンスが返るまでの時間（遅延）を指します。一般的な指標として、**平均レイテンシー（Average Latency）** だけでなく、**パーセンタイルレイテンシー（Percentile Latency）** が使用されます。

### **p95 Latency とは？**
- **p95レイテンシー（95th Percentile Latency）** とは、全リクエストのうち **95% がこの時間以内に処理される** ことを意味します。
- 例えば、p95 レイテンシーが **300ms** なら、「95%のリクエストは300ms以内に処理されているが、5%のリクエストはそれ以上かかっている」という意味です。
- **p50（中央値）よりも、システムの最悪ケースに近いレイテンシーを把握するのに適している**。

| **指標** | **意味** |
|---------|---------|
| p50 | 50% のリクエストがこの時間以内に処理される（中央値） |
| p75 | 75% のリクエストがこの時間以内に処理される |
| **p95** | **95% のリクエストがこの時間以内に処理される** |
| p99 | 99% のリクエストがこの時間以内に処理される（ほぼ最悪ケース） |

---

## **2. どの程度のレイテンシーなら「遅い」のか？**

### **ユースケース別の理想的なレイテンシー基準**

| **ユースケース** | **理想的なp95レイテンシー** | **許容範囲** |
|---------------|----------------------|--------------|
| チャットボット（会話型AI） | **< 500ms** | **1秒以内** |
| 検索エンジン | **< 200ms** | **500ms以内** |
| ストリーミング（字幕生成など） | **< 300ms** | **700ms以内** |
| バックエンドバッチ処理 | **数秒〜10秒** | **15秒以内** |
| 高精度なLLM推論（要約・翻訳） | **1〜2秒** | **5秒以内** |

**1秒を超えると体感的に「遅い」と感じられ、5秒を超えるとユーザーが離脱する可能性が高まる**。

### **レイテンシーが高くなる主な要因**
✅ **モデルサイズが大きい**（例：GPT-4 > GPT-3.5）
✅ **トークン生成速度が遅い**（1秒間に生成できるトークン数が少ない）
✅ **入出力のデータ転送が遅い**（ネットワーク遅延）
✅ **推論時のバッチ処理が適切でない**
✅ **GPUのリソースが不足している**
✅ **非効率な並列化（Multi-GPU, Multi-Nodeが活用されていない）**

---

## **3. 推論APIのレイテンシー改善策**

### **(1) モデルの軽量化**
- **量子化（Quantization）を適用**（例：FP32 → INT8）
- **モデルの蒸留（Distillation）**
- **LoRA（Low-Rank Adaptation）でパラメータ数を削減**

### **(2) バッチ処理の最適化**
- **複数リクエストをまとめて処理（Batch Inference）**
- 適切なバッチサイズを設定（例：バッチサイズが小さすぎるとGPUがアイドル、大きすぎるとオーバーヘッド）

### **(3) GPUの最適化**
- **高性能なGPUを利用する（例：A100, H100）**
- **GPUのメモリ使用量を最適化（Efficient Memory Allocation）**
- **TensorRT・ONNX Runtime などの推論最適化ツールを導入**

### **(4) 分散推論（Multi-GPU / Multi-Node）**
- **DeepSpeed / Tensor Parallelism を活用**
- **Inference Server（vLLM, Triton, Ray Serve）を導入しスケールアウト**

### **(5) キャッシュの活用**
- **過去の推論結果をキャッシュ**（Redis / Memcached）
- **トークンキャッシング（KVキャッシュ）で一部の計算を省略**

### **(6) Kubernetes + HPA の活用**
- **トラフィックに応じた動的スケールアウト（HPA）**
- **VPA を併用し、各 Pod のメモリ・CPU 割り当てを最適化**

---

## **4. まとめ**

### **p95 Latency の重要ポイント**
- **p95レイテンシーとは「95%のリクエストがこの時間以内に処理される」指標**
- 平均レイテンシーよりも、**最悪ケースのパフォーマンスを知るために重要**

### **推論APIのレイテンシー最適化のポイント**
✅ **モデルを軽量化（量子化・LoRA）**
✅ **バッチ処理の最適化（適切なバッチサイズを選定）**
✅ **GPUの高性能化 & メモリ最適化**
✅ **分散推論（Multi-GPU / Multi-Node）**
✅ **キャッシュ（Redis / KVキャッシュ）を活用**
✅ **KubernetesのHPA/VPAでリソース管理を自動化**

LLMの推論APIを最適化することで、**ユーザーの体感速度を向上し、UXを大幅に改善** できます。適切な手法を活用して、最適なパフォーマンスを実現しましょう！
Django(Python)のユーザー認証、SimpleJWTを知ろう！

こんにちは
今回はDjangoのSimpleJWTについてです！

# そもそもJWTってなに？
JWT（JSON Web Token）は、ユーザーの認証情報を安全にやり取りするための仕組みです。
これを使うことで、**サーバーにセッション情報を保存せずに、クライアント側（ユーザーのブラウザなど）で認証**を行うことができます！

# どうやって使われるの？

### 1. ユーザーがログインをする
ユーザーが自分のユーザー名とパスワードを使用してログインしようとします。
この情報をサーバーに送信すると、サーバーは情報が正しいか確認します。

### 2. トークンを取得する
ユーザー情報が正しければ、サーバーはユーザーに「アクセストークン」と「リフレッシュトークン」を返します。
- **アクセストークン**：APIリクエストに使用する短期間のトークン
- **リフレッシュトークン**：アクセストークンが期限切れになったときに新しいトークンを取得するために使うトークン

### 3. APIを利用する
ユーザーは取得したアクセストークンを使用してAPIにアクセスします。(APIにリクエストを送るときは、アクセストークンをヘッダーに含めます)
サーバーはこのトークンを確認して、ユーザーがそのリソースにアクセスできるか判断します。

### 4. トークンの更新
アクセストークンには有効期限があるため、期限が切れる前にリフレッシュトークンを使用して新しいアクセストークンを取得します。
これにより、ユーザーは再度ログインすることなく、継続的にAPIを利用できます。

# ログアウト方法について
 ユーザーがログアウトしたい場合、サーバーに「ログアウト」リクエストを送ります。
 サーバーはそのリクエストに対して、関連するトークンを無効にします。(ブラックリストに追加するなど)

 # まとめ
 DjangoのSimpleJWTを使った認証は、シンプルかつ効率的な認証を行えます。セッション情報を持たないため、特にスケーラブルなアプリケーションにはおすすめです！

---
参考：[SimpleJWT公式ドキュメント](https://django-rest-framework-simplejwt.readthedocs.io/en/latest/)
Macで簡単に並列処理をしたい（OpenMPを使って）

# はじめに
それなりに高性能なMacを持っているので、そのCPUの力を引き出してみようという試みです。（あら、でもさらに高性能な後継モデルがつい先日発表になってしまいましたね、、、）
また、この文章の内容は、筆者が所属している会社・団体とは一切関わりがありません。いわゆる「自主的な研究の成果の発表」というものです。

# OpenMP
簡単に並列処理をするならOpenMPということで。

## 準備
[OpenMP on High Sierra](https://iscinumpy.gitlab.io/post/omp-on-high-sierra/)によると、どうやら、Macの標準のコンパイラ（clang）はOpenMPの機能をサポートしているようです。なので、コンパイラ一式からインストールしなくていいです[^before]。が、ライブラリは入ってなかったりするようなので、その辺りの準備は必要です。(ここから先、基本的には"OpenMP on High Sierra"の内容をなぞってます。が、当然、私のOSは"High Sierra"(macOS 10.13)な訳はなく、"Sequoia"(macOS 15)です。)
[^before]: OpenMPを使うためにコンパイラ（OpenMPに対応したclangとか、gccとか）からインストールしないといけない時代もあったようです。今はずいぶん楽になりました。いい時代になったものです。
~~~
brew install libomp
~~~
が、その前に"brew search"で確認したら、手元のMacではすでにlibompはインストールされているようです。libompそのものをbrewでインストールした記憶はないので、OpenMPの機能を使っているHomebrewのソフトがあって依存関係でインストールされているってことでしょうね。ということで"brew install"はしませんでした。

## コンパイル
諸々適切に設定されているのなら
~~~
cc -fopenmp myprog.c
~~~
でコンパイルできるようです[^GhostBSD]が、普通はそんなことはないでしょう。ということで、以下のようにします。
[^GhostBSD]: あー、確かにGhostBSDならこれだけでできました。そういう環境もあるんですね。
~~~
cc -o myprog -Xpreprocessor -fopenmp -lomp -I"$(brew --prefix libomp)/include" -L"$(brew --prefix libomp)/lib" myprog.c
~~~
（基本的には"OpenMP on High Sierra"の真似です。ccを使ったことのある方なら、やろうとしていることは大体分かるでしょう。）
これで特にエラーも出ることなく、コンパイルできました。

# 実験結果
以下のプログラムで実験してみます。OpenMPでは恒例らしい円周率を求めるプログラムです。
~~~ pi.c
#include <stdio.h>
#include <omp.h>

static long num_steps = 500000000;
long double step;

int main(void)
{
  int i; long double x, pi, sum  = 0.0;

  step = 1.0 / (long double) num_steps;

#pragma omp parallel for reduction(+: sum) private (x)
  for (i = 0; i < num_steps; i++) {
    x = (i + 0.5) * step;
    sum += 4.0 / (1.0 + x * x);
  }
  pi = sum * step;

  printf("%.15Lf\n", pi);

  return 0;
}
~~~
スレッド数は環境変数 OMP_NUM_THREADS で制御できます。まず並列化せずに実行です。
~~~
$ OMP_NUM_THREADS=1 ./pi
3.141592653589814
~~~
3.14...と円周率っぽい値[^pre]が出ているのでよしとしましょう。
[^pre]: 最後の3桁（814）はスレッド数を変更すると変わるので信用してはいけません。が、今回は精度を追求するのが目的ではないので、これでよしとします。

では、スレッド数を変えて実行してみましょう。OMP_NUM_THREADS を1から20まで変更して実行した結果です。
![pi-thread.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535021/38508e34-d274-4cc0-83e7-80d0d5e9ed4e.png)
real、userというのは、それぞれtimeコマンドのreal、userです。8スレッドまではuserはほぼ一定、realが順調に減っているのが分かるかと思います。ということは、全体の処理に掛かる時間はほぼ変わらないものの、処理が適切に分散されているため終了までに掛かる時間が順調に短くなっているということです。一方、9スレッドになるとuserの値が少し増えてしまっています。これは「パフォーマンス」コアが8であることに対応していると考えられます。8よりも多くのスレッドを同時に動かそうとすると、今度は「効率性」コアもスレッドの実行に参入してくるようです。「効率性」コアは「パフォーマンス」コアよりも遅いですから、全体として処理に掛かる時間が増えてしまった、ということでしょう。

# お前の実力はそんなものか
いいえ、違います[^jitsu]。最適化オプション（-O3）すら付けてませんので。実は後からそれに気がついて、-O3を指定して同じことをやってみました。が、傾向は同じでした。（なので、改めてグラフを載せることもしません。）
今回は傾向が見られればそれで満足ですので、以上とします。（はい、私の実力はこんなものでした:sweat:。）さらなる高速化を追求したい方、あとは任せた！
[^jitsu]: もちろん、私の人としての実力ではなくMacのCPUの実力のことですよ:wink:
Azure設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522228/89d33406-1882-4a33-a37b-ad1bb8eb0b53.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522228/fd827a67-79d8-4377-a549-dac71c59540e.png)