KVキャッシュのオフロード戦略とGQAの実践的理解

KVキャッシュのオフロード戦略とGQAの実践的理解

こんにちは!

LLM推論基盤プロビジョニング講座、今回は番外編をお届けします!

第3回「使用モデルの推論時消費メモリ見積もり」では、GPUメモリ消費の二大要素としてモデルのフットプリントKVキャッシュを紹介し、1トークンあたりのKVキャッシュサイズの計算方法を解説しました。

また第4回「推論エンジンの選定」ではvLLMやDeepSpeedなど各推論エンジンの特性を比較し、第5回では量子化や並列化による最適化戦略を解説してきました。

しかし、実はKVキャッシュにはまだまだ掘り下げるべきトピックがあります。

  • KVキャッシュをGPUのVRAMからCPU RAMやディスクにオフロードしたらどうなるのか? どのくらい遅くなるのか?
  • HuggingFace TransformersとvLLMでは、KVキャッシュの管理方針がなぜ根本的に異なるのか?
  • そもそもKVキャッシュが大きくなる原因であるアテンション構造を変えてしまう GQA(Grouped-Query Attention)とは何か? 第5回で紹介した量子化とは別の軸で、KVキャッシュを劇的に小さくする技術です。

今回はこれらのテーマを、PCIe帯域幅の実数値やモデルサイズごとの具体的な計算を交えながら解説していきます。第3回で学んだKVキャッシュの基礎知識があればスムーズに読み進められるとおもいます。

LLM推論基盤プロビジョニング講座 シリーズ記事一覧


KVキャッシュのおさらい

第3回でも解説しましたが、あらためてKVキャッシュの仕組みをおさらいしておきましょう。

Transformerの自己回帰生成(1トークンずつ生成する推論)では、新しいトークンを1つ生成するたびに、全レイヤーを順番に通す必要があります。

トークン1つ生成するために、全部レイヤーぶんの計算するってことになります。原理的には。

処理の流れは以下のとおりです

  1. 新しいトークンの埋め込みがLayer 0に入る
  2. Layer 0で、そのレイヤーの過去のKey・Valueテンソルと合わせてAttentionを計算
  3. その出力がLayer 1に渡る
  4. Layer 1で同様にKVを参照してAttention…
  5. これを最終レイヤーまで繰り返す
  6. 最終レイヤーの出力から次トークンを予測

ただ、ここで重要なポイントは

過去のトークンに対するKeyとValueの計算結果は毎回同じになるという点

です。
ということで毎トークンで再計算するのは無駄なので、
一度計算したKey・Valueをキャッシュしておきます。

これがKVキャッシュですね

このKVキャッシュですが、
コンテキストが長くなるほど大きくなり、VRAMを圧迫していきます。

Transformerの自己回帰生成の仕組み

KVキャッシュのサイズ感

さて、具体的にどのくらいのメモリを消費するのか、(少し古いモデルですが)Llama 2 7Bを例に計算してみましょう。

モデル構成: 32レイヤー、32ヘッド、ヘッド次元128、FP16

まず、1トークンを処理するときに1つのレイヤーで必要になるKVキャッシュのサイズは以下のとおりです

K: 32ヘッド × 128次元 × 2バイト(FP16) = 8 KB
V: 同じく 8 KB
合計: 約16 KB/トークン/レイヤー

つまり、1トークンにつき1レイヤーあたり約16KBのKVキャッシュが蓄積されていきます。

ここで、ユーザーが2048トークン分の文章を入力+生成した状態を考えると

1レイヤーあたり: 16 KB × 2,048トークン = 約32 MB
全32レイヤー合計: 32 MB × 32レイヤー = 約1 GB

この「2048トークン」の部分がコンテキスト長に応じて変わるため、KVキャッシュのサイズはコンテキスト長に比例して大きくなります。

コンテクスト長が8Kトークンなら約4 GB、32Kトークンなら約16 GBがKVキャッシュとして消費されるとうわけです

要するに、ユーザーが大量の文章を入れたり、大量に出力されるような場面では、KVキャッシュもどんどん消費されます

モデルの重み(7B FP16で約14 GB)に加えてこのサイズが必要になりますので、VRAMへの負担は無視できません。


KVキャッシュをCPU RAMやディスクに逃がす

さて、ここで最近話題になるのがコストの高いGPUのRAM(VRAM)の消費量をなるべくおさえたいということで、KVキャッシュをCPU側のメモリやSSDなどのディスクに逃がせないか、といったアイデアです。

結論からいうと、逃すことが可能です。

たとえば、HuggingFace Transformersでは、KVキャッシュをGPUのVRAMからCPU RAMやディスクにオフロードすることができます。

シンプルな方法

KVキャッシュの実体はPyTorchのテンソルなので、.to("cpu") で簡単にCPU RAMに退避できます。

# CPU RAMに退避
cpu_cache = tuple(
    tuple(t.to("cpu") for t in layer)
    for layer in past_key_values
)

# 使うときにGPUに戻す
gpu_cache = tuple(
    tuple(t.to("cuda") for t in layer)
    for layer in cpu_cache
)

ディスクに保存する場合は torch.save を使います。

import torch
torch.save(past_key_values, "kv_cache.pt")
past_key_values = torch.load("kv_cache.pt", map_location="cuda")

HuggingFace の OffloadedCache

Transformers 4.36以降では Cache クラスが導入されており、OffloadedCache を使えばレイヤーごとに自動でCPUオフロードしてくれます。

output = model.generate(
    input_ids,
    cache_implementation="offloaded",
    max_new_tokens=100,
)

内部的には、Layer Nを計算中にLayer N+1のKVキャッシュを非同期でプリフェッチすることで、転送のオーバーヘッドを緩和しています。

KVキャッシュをRAMやSSDにオフロードする仕組み

オフロードのボトルネック:PCIe転送速度

さて、技術的にはKVキャッシュをGPUの中から追い出す=オフロードすることは可能ですが、ここでまず問題になるのがKVキャッシュをGPU外に出す、KVキャッシュを読み取るときの読み書きスピードです。

CPU ↔ GPU間のデータ転送はPCIeバスを介して行われます。

で、そのスピード、つまり、帯域幅はPCIのバージョンと使えるレーン数で決まります。

PCIe世代 x16 片方向帯域 実効スループット
PCIe 3.0 約16 GB/s 約12〜13 GB/s
PCIe 4.0 約32 GB/s 約25 GB/s
PCIe 5.0 約64 GB/s 約50 GB/s

実際にどのくらい遅くなるか

ちょっとふるいですが、Llama 2 7B(32レイヤー、FP16)、コンテキスト2048トークンの場合で見積もってみましょう。

先ほど説明したとおり、1トークン生成するごとに全レイヤーを通す必要がありますので、各レイヤーのKVキャッシュをGPUに転送 → 計算 → CPUに戻す、というサイクルが発生します

さきほどの2048トークンぶんの分量ですと、1レイヤーあたり約32 MB × 32レイヤー = 約1 GBの転送量になりますので、PCIe 4.0(実効25 GB/s)なら片道約40msかかります。

シナリオ 速度
GPU のみ(VRAM内完結) 約15 ms/token
オフロード(プリフェッチなし) 約80 ms以上/token
オフロード(プリフェッチあり) 約40〜50 ms/token

これを、GPUのみで完結する場合とくらべますと、おおよそ 3〜5倍遅くなる 計算です。
PCI転送だけでこれだけ遅くなります。

ただ、mレイヤーは順番に処理されるので、Layer Nの計算中にLayer N+1を非同期転送する「パイプライン化」が可能ですので、計算時間が転送時間を上回る場合は、転送コストを隠蔽できます。
逆に長コンテキストで1レイヤーあたりの転送量が大きくなると、計算時間を超えてしまいボトルネックになります。

コンテキスト長と転送コストの関係

コンテキスト長 1レイヤーKVサイズ 全レイヤー転送量 転送時間(PCIe 4.0)
2K 32 MB 約1 GB 約40 ms
8K 128 MB 約4 GB 約160 ms
32K 512 MB 約16 GB 約640 ms

32Kコンテキストでは1トークンの生成に0.6秒以上かかる計算になり、リアルタイム用途ではかなり厳しくなります。
たとえ、PCIを4.0の2倍程度はやくなるPCI5.0にしてもリアルタイム用途では厳しいです。

ディスク(SSD)への保存はさらに遅く、NVMe SSDで3〜7 GB/s、SATA SSDで約0.5 GB/sです。

これでは、リアルタイム推論には向かず、セッション間でキャッシュを再利用する用途に限られるというのが実情です。


vLLMとの設計思想の違い

第4回でvLLMとHuggingFace Transformers(QCT)の違いを紹介しましたが、ここではKVキャッシュ管理の観点からもう少し掘り下げてみましょう。

HuggingFace Transformersや当社独自のQCTをつかう場合、アーキテクチャがシンプルでKVキャッシュのオフロードが比較的やりやすいのですが、vLLMだと実はKVキャッシュのオフロードの難易度が高くなります。

なぜなら同じKVキャッシュの管理でも、両者はまったく異なるアプローチを取っているからです。

HuggingFace Transformers

  • シンプルなforループでレイヤーを1つずつ順番に処理します
  • 各レイヤーのKVキャッシュを好きなタイミングで出し入れできます
  • 基本的に1リクエストずつのシーケンシャル処理です
  • バッチ処理やプロトタイピングに向いています

vLLM

  • PagedAttention でKVキャッシュを固定サイズブロックに分割し、VRAM内で効率管理します
  • 連続バッチング で複数リクエストを同時処理します
  • 基本的に全部VRAMに載る前提で設計されています
  • 同時数十リクエストを捌き、スループット数百〜1000+ tokens/secを実現します

vLLMにもKVキャッシュのCPUスワップ機能は存在しますが、推論中に毎トークン転送するのではなく、リクエストがプリエンプト(中断)されたときにそのリクエストのKVブロックをCPUに退避し、再開時に戻すというスケジューリングの一環として使われます。

HF OffloadedCache vLLM
目的 VRAMに入らないKVを退避 スケジューリングで一時退避
タイミング 毎トークン、レイヤーごと リクエスト中断/再開時
レイテンシ影響 常に遅くなる 退避中のリクエストだけ遅延

なぜこの違いが生まれるか

HuggingFace Transformersはシンプルな単一リクエストの推論ループだからこそ、各レイヤーで .to("cpu") / .to("cuda") を挟むだけでオフロードが実現できます。一方、vLLMは連続バッチングで複数リクエストを同時処理しているため、毎レイヤーでPCIe転送を待つとパイプライン全体が詰まってしまいます。

これは柔軟性 vs スループットのトレードオフです。

個人で大きいモデルを動かしたいならHFのオフロード、複数ユーザーへのサービングならvLLMでVRAMに収まる構成を選ぶのが定石になります。

さらに、vLLMはモデルアーキテクチャごとの最適化も随所にいれており、スループットを出せるぶん、リアルタイムなKVキャッシュオフロードを手軽にやるのがかなり難しくなっています。

HuggingFace TransformersとvLLMの設計思想の違い

HuggingFace Transformersの同時処理能力

同時処理能力についてもみておきましょう。

HuggingFace Transformers単体では、基本的に1リクエストずつの処理になります。model.generate() は同期的・ブロッキングで、並行処理の仕組みは内蔵されていません。

ただし、FastAPIなどでラップしてマルチスレッドで model.generate() を呼ぶ場合、VRAMに余裕があれば2〜3リクエストが同時に走ることはあります。PyTorchのCUDAは同一GPU上で複数カーネルをある程度並行実行できるためです。

方法 同時処理数 備考
素のHF 1
マルチスレッド + FastAPI 2〜3 VRAM次第
複数GPUで複数プロセス GPU数分 メモリ×N
HF TGI 数十〜 vLLM寄りの設計

とはいえ、各リクエストが独立にアテンション計算を行うため、バッチ化の恩恵がなくVRAM効率は良くありません。vLLMとの差はスループットで文字通り桁違いになります。

バッチ処理ならHFが輝く

一方で、オフラインのバッチ処理ならHuggingFace Transformersは良い選択肢です。

  • リアルタイム性が不要なので、オフロードの遅延も許容できます
  • 1件ずつ順番に処理すればよく、並行処理の複雑さがありません
  • コードがシンプルで、前処理・後処理のカスタマイズが自由です
  • KVキャッシュをディスクに保存して再利用できます

大量のドキュメント要約、データセットへのラベル付け、夜間バッチ推論など、「寝ている間に終わればいい」用途には十分実用的です。


小さいGPUで大きいモデルを動かす

KVキャッシュのオフロードだけでは不十分で、モデルの重みがVRAMに載らなければそもそも動きません。

GPU VRAMに必要なもの

対象 7B FP16 70B FP16
モデルの重み 約14 GB 約140 GB
KVキャッシュ 1〜数 GB 10 GB〜
アクティベーション 数百 MB 数 GB

device_map="auto" による自動分配

HuggingFace Transformersの device_map="auto" を使えば、VRAMに入るレイヤーはGPUに、残りはCPU RAMに、それでも入らなければディスクに自動配置されます。

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-70b-hf",
    device_map="auto",
    offload_folder="offload",
)

これなら8GBのGPUでも70Bモデルが一応動きます。ただし速度は大幅に低下します。

構成 70Bの速度感
全部GPU(A100 80GB × 2) 約30 tokens/sec
GPU + CPUオフロード 約2〜5 tokens/sec
GPU + ディスクオフロード 約0.1〜0.5 tokens/sec

量子化との組み合わせ

第5回で解説した量子化と組み合わせるのが最も現実的です。モデルサイズを小さくしたうえでオフロードを使います。

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-70b-hf",
    load_in_4bit=True,          # 140GB → 約35GB
    device_map="auto",          # 残りはCPUへ
)

24GB GPU 1枚で完結するモデルサイズの目安(4bit量子化時)

モデル 4bitサイズ 24GBに載る?
7B 約4 GB 余裕
13B 約7 GB 余裕
30B 約17 GB ギリギリ載る
70B 約35 GB 載らない

70Bの4bit(約35GB)は24GBのVRAMには収まりません。device_map="auto" で半分程度をCPU RAMに配置することで動作はしますが、CPU上のレイヤー処理は遅くなります。GPU 1枚で完結させたいなら、24GB × 2枚(48GB)か、A6000(48GB)やA100(80GB)が必要です。


KVキャッシュのCPUオフロードが活きるシナリオ

ここまで読んで「オフロードは遅くなるだけでは?」と思われたかもしれません。KVキャッシュ「だけ」をCPUに逃がして意味がある場面は、モデルの重みはGPUに載るが、コンテキストが長くてKVキャッシュがVRAMを溢れる場合です。

30Bモデル × 24GB GPUの具体例

30Bモデルを4bit量子化(約17GB)で24GB GPUに載せると、残り約9GBをKVキャッシュに使えます。

GQA対応モデル(KVヘッド8)の場合、1トークンあたりのKVキャッシュサイズは以下のとおりです:

K + V: 64レイヤー × 8ヘッド × 128次元 × 2バイト × 2(KV) = 256 KB/トークン

9GBで約36,000トークン分のKVキャッシュが格納できます。フルアテンション(KVヘッド64)なら約4,500トークンで一杯になります。

KVヘッド構成 9GBで入るトークン数
GQA(KV 8ヘッド) 約36K
MQA(KV 1ヘッド) 約288K
フルアテンション(64ヘッド) 約4.5K

この表をみると、同じ9GBでもアテンション方式によって格納できるトークン数が桁違いに異なることがわかりますね。GQAについては次のセクションで詳しく解説します。

有効なユースケース

  1. 長文書のバッチ分析 — 論文や契約書を丸ごと入力して要約します。バッチ処理なので遅くてもOKです
  2. RAGで大量チャンクを一度に入力 — 検索で絞らず全部コンテキストに突っ込んで精度を上げたい場合に有効です
  3. KVキャッシュの再利用 — 同じシステムプロンプト(数千トークン)のプリフィル結果をCPU RAMに保持しておき、リクエストごとにGPUに転送します。長いプロンプトだと、毎回プリフィルを再計算するよりPCIe転送の方が速くなる逆転ポイントがあります

GQA/MQA — KVキャッシュ問題を根本から緩和する

ここまではKVキャッシュの「運用」を見てきましたが、そもそもKVキャッシュが大きくなる原因はAttentionヘッドの数にあります。これを構造的に解決するのがGQA(Grouped-Query Attention)とMQA(Multi-Query Attention)です。

第5回では量子化によってモデルのフットプリントを小さくするアプローチを紹介しましたが、GQAはそれとは別の軸で、アテンション構造そのものを変えてKVキャッシュを劇的に小さくする技術です。

MHA(Multi-Head Attention)— 従来方式

Query、Key、Valueそれぞれが同じ数のヘッドを持ちます。

Q: 64ヘッド
K: 64ヘッド  ← 全部独立
V: 64ヘッド  ← 全部独立

MQA(Multi-Query Attention)— 極端な共有

2019年にGoogleのNoam Shazeerが論文「Fast Transformer Decoding: One Write-Head is All You Need」で提案しました。KとVを全ヘッドで共有します。

Q: 64ヘッド
K: 1ヘッド   ← 全Qヘッドがこの1つを共有
V: 1ヘッド

KVキャッシュが1/64になります。推論速度は大幅に向上しますが、品質がやや落ちるのが課題でした。

GQA(Grouped-Query Attention)— バランスの取れた中間

2023年5月にGoogleのJoshua Ainslieらが論文「GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints」(arXiv:2305.13245)で提案しました。Qヘッドをグループに分けて、グループごとにK, Vを共有します。

Q: 64ヘッド(8グループ × 8ヘッド)
K: 8ヘッド   ← 各グループに1つ
V: 8ヘッド

KVキャッシュが1/8になり、品質と効率のバランスが優れています。

視覚的なイメージ

MHA:  Q₁→K₁  Q₂→K₂  Q₃→K₃  Q₄→K₄  (各自専用)
GQA:  Q₁→K₁  Q₂→K₁  Q₃→K₂  Q₄→K₂  (グループで共有)
MQA:  Q₁→K₁  Q₂→K₁  Q₃→K₁  Q₄→K₁  (全員同じ)
MHA・GQA・MQAの3つのアテンション方式

GQAの動機

KVキャッシュ削減が主要な動機の一つですが、それだけではありません。自己回帰生成のボトルネックは計算ではなくメモリ帯域です。毎トークンで巨大なKVキャッシュをVRAMから読み出す必要があります。

つまり、KVキャッシュのサイズ(VRAM容量の問題)と読み出し帯域(速度の問題)の両方を同時に改善することが目的です。推論のメモリ帯域ボトルネックを解消する中で、KVキャッシュ削減も自然についてきたという方が正確でしょう。


GQAの採用タイムライン

GQAの論文発表から実際のモデルへの搭載は非常に速く、わずか2ヶ月で業界の主要モデルに採用されました。以下、各ソースで裏取りしたタイムラインをまとめます。

時期 モデル 方式 備考
2019年 MQA論文(Shazeer) MQAの提案 「Fast Transformer Decoding」
2022年4月 PaLM(Google) MQA 大規模モデルとしてMQAを初採用
2023年5月 GQA論文(Ainslie et al.) GQAの提案 arXiv:2305.13245
2023年5月頃 Falcon 7B / 40B MQA / GQA 7Bは1グループ(MQA相当)、40Bと175Bは8グループ
2023年7月 Llama 2 GQA(8グループ) 70Bのみ。7Bと13BはMHAのまま
2023年10月 Mistral 7B GQA(8グループ) 小型モデルでもGQA採用
2023年12月 Mixtral 8x7B GQA(8グループ) MoEアーキテクチャでもGQA
2024年4月〜 Llama 3 全サイズ GQA(8グループ) 8B〜405Bまで全サイズでGQA
以降 ほぼ全ての新規モデル GQA Gemma, Qwen, OLMo等も採用

注目すべきは、Llama 2の7Bと13BはフルアテンションのMHAのままで、70Bだけ にGQAが採用された点です。小さいモデルではKVキャッシュがそこまで問題にならないという判断でしたが、Llama 3以降はすべてのサイズでGQAが標準になっています。

また、GQA論文の正式な学会発表は2023年12月のEMNLP(シンガポール)でしたが、arXivプレプリントが2023年5月に公開された直後から各社が採用に動いており、それだけ業界全体でKVキャッシュが切実な課題だったことの裏返しと言えます。


まとめ:実践的な判断フロー

最後に、ここまでの内容を踏まえた実践的な判断フローを整理しておきましょう。

モデル選定時: GQA対応モデルを選びましょう。最近のモデル(Llama 3以降、Mistral等)はほぼ全てGQA対応で、KVキャッシュが大幅に小さくなっています。

VRAMが足りないとき

  1. まず量子化(4bit/8bit)でモデルサイズを圧縮
  2. それでも入らなければ device_map="auto" でCPU RAMにオフロード
  3. KVキャッシュだけ溢れる場合は cache_implementation="offloaded" を使用
  4. サービングなら量子化 + vLLMでVRAMに収まる構成を選ぶ

用途で使い分ける

  • 個人のバッチ処理 → HuggingFace Transformers + オフロード。遅くても動けばOKです
  • 複数ユーザーへのサービング → vLLMまたはTGI。VRAMに収まる構成が前提です
  • プロトタイピング・研究 → HuggingFace Transformers。コードがシンプルでカスタマイズしやすいです
LLM推論の用途別判断フローチャート

KVキャッシュは「見えないVRAM消費者」として軽視されがちですが、コンテキスト長が伸びる昨今のLLMでは、その管理が推論パフォーマンスを左右する重要なファクターになっています。GQAの普及によって状況はかなり改善されましたが、128Kトークンのような超長コンテキストでは依然としてKVキャッシュの扱いが鍵を握ります。

自分の用途とハードウェアに合わせた戦略を選ぶことが、快適なLLM推論への近道です。

それでは、また次の記事でお会いしましょう!

LLM/AIセキュリティのことなら株式会社Qualiteg

私たちQualitegは、LLMの推論・サービング基盤を実際に設計してきたエンジニアリングチームを有しており推論エンジンを単なる箱として扱わず、アテンション計算やKVキャッシュの挙動など深い知見をベースにしたローカルLLM技術のご支援を提供しています。「VRAMに収まる構成はどこか」「vLLMとHugging Face、判断軸は何か」「既存モデルを自社ドメインへ適応させる最短経路は」「オープンLLMと商用LLMの使い分け」「セキュアなローカルLLM構成はどうすればいいか」「ローカルLLMとGPUの選び方」「GPUデータセンターの需要と市場予測」「AI市場予測」などコア技術からAI市場分析まで、お気軽にご相談くださいませ。

AI Technology Consulting | Qualiteg

Read more

Python と JavaScript で絵文字の文字数が違う!サロゲートペアが引き起こす位置ずれバグの話

Python と JavaScript で絵文字の文字数が違う!サロゲートペアが引き起こす位置ずれバグの話

こんにちは! Qualitegプロダクト開発部です! PII(個人情報)検出のデモアプリを開発していて、検出したエンティティの位置をハイライト表示する機能を実装していました。 バックエンドは Python(FastAPI)、フロントエンドは JavaScript という構成です。 ある日、テストデータにこんなメール文面を使ったところ、ハイライトの位置が途中から微妙にずれるバグに遭遇しました。 鈴木一郎 様 いつもお世話になっております。 サンプル商事の佐藤でございます。 先日の件、確認が取れましたのでご連絡いたします。 お忙しいところ恐縮ですが、ご確認のほど宜しくお願い致します。 💻 #オンラインでのお打ち合わせ、お気軽に声がけください! ―――――――――――――――――――――――――――――― サンプル商事株式会社 営業部 第一課 山田 太郎 (Yamada Taro) 〒100-0001 東京都千代田区千代田1-1-1 サンプルビル 3F tel: 03-1234-5678 https://example.com/contact 検出結果をハイライト表示

By Qualiteg プロダクト開発部
大企業のAIセキュリティを支える基盤技術 - 今こそ理解するActive Directory 第5回 ブラウザ設定と認証

大企業のAIセキュリティを支える基盤技術 - 今こそ理解するActive Directory 第5回 ブラウザ設定と認証

こんにちは、今回はシリーズ第5回「ブラウザ設定と認証」について解説いたします! さて、前回(第4回)では、プロキシサーバーをドメインに参加させることで、ChatGPTやClaudeへのアクセスを「誰が」行ったかを確実に特定する仕組みを解説しました。「信頼の連鎖」の概念や、Windows版Squidなら1時間で構築できる環境、Negotiate/NTLM/Basicという3段階の認証フォールバック機構について理解いただけたかと思います。 しかし、せっかくサーバー側で完璧な統合Windows認証環境を構築しても、ブラウザ側の設定が適切でなければ、ユーザーには毎回パスワード入力ダイアログが表示されてしまいます。 「Edgeだと自動でログインできるのに、Chromeだとパスワードを聞かれる」 「同じサーバーなのにURLの書き方で動作が違う」 これらはヘルプデスクに寄せられる典型的な問い合わせです。(ただ、業務に好きなブラウザ使っていいよ、という企業はそんなに多くはないとおもいます) 今回は、統合Windows認証がブラウザでどのように動作するのか、その仕組みから各ブラウザ(Edge/

By Qualiteg AIセキュリティチーム, Qualiteg コンサルティング
スライドパズルを解くAIから学ぶ、「考える」の正体

スライドパズルを解くAIから学ぶ、「考える」の正体

こんにちは! 「このパズル、AIの教科書に載ってるらしいよ」 子供の頃に遊んだスライドパズル。いや、大人が遊んでも楽しいです。 数字のタイルをカチャカチャ動かして揃えるあれです。実はこのシンプルなパズルが、AI研究の出発点のひとつだったって知ってました? 今回は、このパズルを題材に「AIがどうやって考えているのか」を解き明かしていきます。しかも、ここで使われている手法は、Google Mapsの経路探索からChatGPTまで、現代の様々な技術のベースになっているんです。 まず遊んでみよう 理屈の前に、まずは感覚を思い出してみてください。 最初に shuffle をクリックすると、配置がシャッフルされゲームを開始できます。 ちなみに必ず解くことができるようになっていますが、慣れていないとそれなりに難しいかもしれません。 どうでしょう? 何手でクリアできましたか? クリアできなくても大丈夫です。記事後半で、実際にAIが解いてくれる機能つきゲームも掲載しています^^ 以下は動画です。本ブログで紹介するアルゴリズムで実際にパズルを解く様子をご覧いただけます

By Qualiteg 研究部
楽観的ロック vs 悲観的ロック:実際のトラブルから学ぶ排他制御

楽観的ロック vs 悲観的ロック:実際のトラブルから学ぶ排他制御

こんにちは! Qualitegプロダクト開発部です! 「楽観的ロックを実装したのに、まだ競合エラーが出るんですけど...」 これは私たちが実際に経験したことです。 本記事では、楽観的ロックと悲観的ロックの違いを、実際に発生したトラブルを通じて解説します。 抽象的な説明ではなく、 「なぜそれが必要なのか」「どんな問題を解決できるのか」 を実感できる内容を目指します。 目次 1. 問題の背景:並列処理で謎のエラー 2. ロックなしの世界:なぜ競合が起きるのか 3. 楽観的ロックの導入:期待と現実 4. 楽観的ロックの限界:解決できなかった問題 5. 悲観的ロックによる解決 6. 実装時のハマりポイント 7. どちらを選ぶべきか:判断基準 8. まとめ 1. 問題の背景:並列処理で謎のエラー 1.1 システムの概要 私たちが開発していたのは、 複数のワークスペースを切り替えて使用するAPIサーバー でした。 当社AI関係のプロダクトの一部だったのですが、結合テスト兼負荷テストを実行すると、まれに発生してしまっていました。 ユーザーは複数のワーキン

By Qualiteg プロダクト開発部