今回も、先日受験した令和6年度秋期試験の午前Ⅰ共通問題の解説を行っていきます。
今回解説するのは、問6〜10です。これらの問題で使用されていた用語は、以下の5つです。
- ページング方式
- コンパイラのコード生成
- アクチュエーター
- 帯域幅の計算方法
- データベースの設計
是非、最後までご覧いただけると嬉しいです。
ページング方式
仮想記憶方式において、セグメンテーション方式と比較した場合のページング方式の長所はどれか。
ア 記憶領域へのアクセス保護を論理的な単位で行うことができる。
イ 記憶領域をプログラム間で容易に共用することができる。
ウ 実行時に記憶領域の大きさを動的に変えことができる。
エ 主記憶の外部断片化が発生しない。
引用:情報処理安全確保支援士試験 令和6年 秋 午前Ⅰ問6
解答
エ
問題の解説
仮想記憶方式において、ページング方式とセグメンテーション方式には、それぞれ以下の特徴があります。
ページング方式の特徴
- 固定長のページ(通常4KBや8KBなどのサイズ)にプログラムやデータを分割します。
- 主記憶も同じ固定長のページフレームに分割されます。
- 必要なページのみ主記憶にロードし、ページテーブルを用いて管理します。
メリット
- 主記憶の外部断片化が発生しない。 主記憶が固定サイズのページフレームで管理されるため、ページ単位で効率的に空き領域を利用できます。
- プログラムやデータの配置場所を意識する必要がなく、メモリ管理が単純化されます。
デメリット
- 内部断片化が発生する可能性がある。 プログラムがページサイズに満たない場合、余った部分のメモリが無駄になります。
セグメンテーション方式の特徴
- プログラムを論理的な単位(例:関数、配列、スタックなど)に分割します。
- 各セグメントは可変長で管理されます。
メリット
- 記憶領域をプログラム間で共用しやすい。(例:ライブラリやデータを複数プログラムで共有)
- 記憶領域のアクセス保護が論理的な単位で可能。 各セグメントに対してアクセス権を設定できます。
デメリット
- 外部断片化が発生する可能性がある。 可変長のセグメントを管理するため、主記憶内に隙間ができやすくなります。
各選択肢の検討
- ア:記憶領域へのアクセス保護を論理的な単位で行うことができる。
→ これはセグメンテーション方式の特徴です。ページング方式ではアクセス保護はページ単位で行われ、必ずしも論理的な単位ではありません。 - イ:記憶領域をプログラム間で容易に共用することができる。
→ セグメンテーション方式では、論理的な単位でメモリを分割するため、記憶領域を共用しやすいという特徴があります。ページング方式はこれに特化していません。 - ウ:実行時に記憶領域の大きさを動的に変えることができる。
→ セグメンテーション方式の特徴です。可変長のセグメントを扱うため、動的なサイズ変更が可能です。ページング方式では固定サイズのページ単位で管理するため、これを直接サポートしていません。 - エ:主記憶の外部断片化が発生しない。
→ ページング方式の特徴です。固定長のページフレームを使用することで、外部断片化を回避できます。
ページング方式のまとめ
ページング方式は、プログラムやデータを固定長のページに分割し、必要なページだけを主記憶に読み込むことで、メモリを効率的に利用できる方式です。外部断片化を抑制し、大規模なプログラムの実行を可能にします。また、参照の局所性を考慮することで、高速なアクセスを実現します。
コンパイラのコード生成
手続型言語のコンパイラがコード生成までに行う処理のうち、最後に行うものはどれか。
ア 意味解析
イ 構文解析
ウ 最適化
エ 字句解析
引用:情報処理安全確保支援士試験 令和6年 秋 午前Ⅰ問7
解答
ウ
手続型言語の処理
手続型言語のコンパイラは、コードを効率的に実行できる形に変換するために、いくつかの処理を順番に行います。それぞれの処理の内容と順序を以下に説明します。
1. 字句解析 (Lexical Analysis)
字句解析(Lexical Analysis)は、ソースコードを入力として受け取り、そのコードを小さな構成要素(トークン)に分割するプロセスです。この解析は、コンパイラの最初の段階であり、構文解析やコード生成といった後続の処理に必要な基礎データを提供します。
以下に、字句解析の概要とその具体的な役割について説明します。
字句解析の役割
- 入力の分割
ソースコードを文字列として読み取り、キーワード、識別子、リテラル、演算子、区切り記号(例:;
,{
,}
)などの構成要素に分割します。 - トークンの生成
分割した構成要素をトークンとして出力します。トークンは、特定の種類(トークンタイプ)とその値(例えば、識別子の名前や数値リテラル)を持ちます。 - 入力の正当性検証
字句解析では、トークン化の過程で文字列が言語仕様に従っているかを検証します。たとえば、無効な文字や不正な識別子名がある場合、エラーを報告します。
字句解析のプロセス
- 入力の読み込み
ソースコードは通常、1行ずつまたは一定の文字単位で読み取られます。 - 文字列のパターンマッチング
正規表現や状態遷移図(有限状態オートマトン)を用いて、コードの文字列をトークンに分割します。状態遷移図(有限状態オートマトン)とは、システムやプロセスが取ることのできる状態と、それらの状態間を遷移する条件を視覚的に表現した図です。 - トークンタイプの識別
- キーワード:
if
,while
,return
など、言語で予約されている単語。 - 識別子: ユーザーが定義する変数名や関数名。
- リテラル: 数値リテラル(例:
42
)、文字列リテラル(例:"hello"
)。 - 演算子:
+
,-
,*
,/
など。 - 区切り記号:
(
,)
,{
,}
,;
など。
- キーワード:
- トークンの出力
各トークンをデータ構造(通常はリストやキュー)に保存し、構文解析器に渡します。
字句解析の成果物例
以下は、簡単なソースコード int x = 42;
を字句解析した結果の例です:
トークンタイプ | 値 |
---|---|
キーワード | int |
識別子 | x |
演算子 | = |
数値リテラル | 42 |
区切り記号 | ; |
字句解析は、プログラムの構文的な構造を把握する第一歩であり、エラーを早期に検出するための重要なプロセスです。
2. 構文解析 (Syntax Analysis)
構文解析(Syntax Analysis)は、字句解析(Lexical Analysis)の次の段階であり、入力されたトークン列を基にソースコードの文法構造を解析します。このプロセスでは、プログラムが言語の文法に従っているかどうかを検証し、トークンを構造化されたデータ形式(通常は構文木または抽象構文木)に変換します。
以下では、構文解析の役割や手法について詳しく説明します。
構文解析の役割
- 文法規則の適用
プログラムが対象言語の文法に従っているかを確認します。文法は通常、文脈自由文法で記述されます。 - 構文木の生成
ソースコードの文法構造を階層的に表現する構文木(Parse Tree)または抽象構文木(AST : Abstract Syntax Tree)を構築します。 - エラーチェック
文法に違反するコードを検出し、エラーメッセージを生成します。これには、構文エラー(例: 括弧の不一致)や予期しないトークン(例:if
文に続くブロックがない)などが含まれます。 - 次の段階への準備
構文木やASTは、後続のセマンティック解析(意味解析)や最適化の入力として使用されます。
構文解析のプロセス
- 文法の定義
言語の文法は、バックナウア記法やその変種で記述されます。たとえば、簡単な式文法は以下のように定義されます。 - トークン列の入力
字句解析器からのトークン列を受け取り、それに基づいて解析を行います。 - 構文解析アルゴリズムの適用
トークン列に対して以下のいずれかの手法を用いて構文解析を行います:- トップダウン構文解析
文法規則を上位(開始記号)から展開し、トークン列に対応する構文木を構築します。- 再帰下降解析:手続き型で実装される解析法。
- LL解析:左から右への入力を解析し、左端展開を行う。
- ボトムアップ構文解析
トークン列を下位から解析し、構文規則を逆に適用して構文木を構築します。- LR解析:最も一般的なボトムアップ解析法。
- SLR解析、LALR解析:LR解析の簡易版または拡張版。
- トップダウン構文解析
- 構文木の生成
成功した場合、ソースコードの構造を階層的に表現する構文木を生成します。
構文解析は、コードの文法的な正しさを検証し、ソースコードを機械が扱いやすい形に変換する重要なステップです。模索型言語の柔軟な記述が許容される場合でも、文法規則に基づく正確な解析が求められます。
3. 意味解析 (Semantic Analysis)
意味解析 (Semantic Analysis) は、構文解析によって生成された構文木や抽象構文木 (AST) を基に、プログラムの文法的な正しさを超えて意味的な正しさを検証する段階です。このプロセスでは、文脈に基づいてプログラムの各部分が正しく機能するかを確認し、適切な中間表現やエラーメッセージを生成します。
意味解析の目的
- 型検査
各式や変数、関数などの型が正しいか確認します。たとえば、int
型の変数にstring
を代入する操作は無効とみなされます。 - 識別子の解決
変数、関数、クラスなどの識別子が適切に宣言され、スコープ内で使用されているか確認します。 - 制約の検証
言語仕様に基づく制約(例: 配列のインデックスが整数型であること、関数呼び出しの引数の数や型が一致することなど)を確認します。 - 中間表現の生成
後続の最適化やコード生成の基礎となる中間表現を構築します。
意味解析の主なタスク
1. 型検査
型検査では、式の評価結果や変数への代入が型に適合しているかを検証します。
- 型一致の確認
int x = "hello"; // エラー: string を int に代入
- 型の昇格(型変換)
必要に応じて型の昇格を許容します(例:int
をfloat
に変換)。
2. スコープと名前空間の解析
プログラム内の各識別子が正しいスコープ内で宣言され、適切に使用されているかを検証します。
- 未宣言変数の検出
y = 10; // エラー: y が未宣言
- スコープルールの適用
関数内のローカル変数が、グローバル変数と衝突しないことを確認します。
3. 宣言と使用の一致
識別子が宣言された型や構造と一致して使用されているかを確認します。
- 関数の引数の型検査
void foo(int a) { ... } foo("hello"); // エラー: int が期待される場所に string
4. 制約の検証
特定の言語に固有の文法ルールや意味的な制約を確認します。
- 配列のインデックスが有効な型であるか
break
やcontinue
がループ内でのみ使用されているかreturn
文が関数の戻り値の型と一致しているか
5. 型推論
模索型言語では型推論が重要になる場合があります。型が明示的に指定されていない場合でも、コンパイラは文脈に基づいて型を推定します。
- 型推論
var x = 5; // x の型は int と推論され
ます。
6. 属性付け
AST に追加情報(属性)を付加します。これには型情報、スコープ情報、メモリ配置情報などが含まれます。この情報は中間コード生成で利用されます。
意味解析の成果物
- 修飾された AST
構文木や抽象構文木に型やスコープの情報を付加したもの。 - シンボルテーブル
識別子(変数、関数、クラスなど)の名前、型、スコープ、メモリ位置などを管理するデータ構造。 - 中間コード
後続の最適化やコード生成に利用される低レベルな中間表現。
4. 最適化 (Optimization)
模索型言語のコンパイラにおける最適化 (Optimization) とは、ソースコードから生成される実行コードを効率的にするためのプロセスです。最適化の目的は、プログラムの動作を変えることなく、実行速度を向上させたり、メモリ消費量を減少させたりすることです。
模索型言語は柔軟な文法や実行時の動的な特性を持つことが多く、最適化の難易度が高まることがあります。しかし、適切な最適化を行うことで、模索型言語の実行パフォーマンスを大幅に向上させることが可能です。
最適化の分類
最適化は、主に以下の2つの段階で行われます:
- 中間表現(IR: Intermediate Representation)の最適化
コンパイラが生成する中間表現を基に行う最適化。コードの構造的な改善に注力します。 - ターゲットコード(マシンコード)の最適化
実行環境やプロセッサに依存する最適化。ハードウェアに合わせた効率化を行います。
また、最適化にはローカル最適化(基本ブロック内での最適化)とグローバル最適化(関数やプログラム全体を対象とする最適化)があります。
最適化の種類
1. コード簡約(Code Simplification)
無駄な計算や不要な命令を削除します。
- 定数畳み込み (Constant Folding)
コンパイル時に定数の計算を行う最適化。 - 不要コードの除去 (Dead Code Elimination)
実行されないコードや使用されない変数を削除します。
2. ループ最適化 (Loop Optimization)
プログラムの中で頻繁に実行されるループを効率化します。
- ループ不変コードの外出し (Loop-Invariant Code Motion)
ループ内で繰り返し実行する必要のない計算をループ外に移動します。 - ループ巻き上げ (Loop Unrolling)
ループの反復回数を減らすために、ループ本体を複製します。
3. 関数呼び出しの最適化
- インライン展開 (Inline Expansion)
小さな関数の呼び出しを直接展開することで、関数呼び出しのオーバーヘッドを削減します。
4. 共通部分式の除去 (Common Subexpression Elimination)
同じ計算式が繰り返し評価されている場合、その結果を再利用します。
例:
y = (a + b) * (a + b)
最適化後:
temp = a + b
y = temp * temp
5. メモリ操作の最適化
メモリアクセスを削減し、キャッシュ効率を向上させます。
- レジスタ割り当て (Register Allocation)
頻繁に使用される変数をメモリではなくレジスタに格納します。 - ループのキャッシュ最適化
ループ内のデータアクセスをキャッシュフレンドリーな方法に再構成します。
6. プラットフォーム依存の最適化
プロセッサやハードウェアの特性を活用する最適化。
- ベクトル化 (Vectorization)
SIMD命令を使用して、複数のデータを同時に処理します。SIMD(Single struction, Multiple Data)命令とは、1つのコマンドで複数のデータを同時に処理することで、高速化を実現するライブラリ処理技術です。 - 命令スケジューリング
プロセッサパイプラインを効率的に使用するために命令の順序を変更します。
結論
コンパイラにおける最適化は、模索型言語のパフォーマンスを大幅に向上させる重要なプロセスです。しかし、模索型言語特有の動的な性質により、最適化には慎重な設計が求められます。コンパイラの設計者は、プログラムの正確性を保ちながら、実行効率を最大化する方法を常に模索する必要があります。
5. コード生成 (Code Generation)
模索型言語のコンパイラにおけるコード生成 (Code Generation) は、意味解析や最適化の結果をもとに、ターゲットプラットフォームで実行可能なコード(マシンコードやバイトコードなど)を生成する段階です。このプロセスは、コンパイラの最終段階にあたり、正確かつ効率的なコードを作り出すことを目的とします。
コード生成の基本概要
コード生成の目標は以下の3点です:
- 正確性
ソースコードの意味を正確に保持し、期待通りの動作を実現するコードを生成します。 - 効率性
実行速度やリソース使用量を最適化したコードを作成します。 - 移植性(必要に応じて)
ターゲットプラットフォームが異なる場合でも、適切な実行形式を生成します(例: バイトコードや異なるプロセッサ向けの機械語)。
コード生成の主なステップ
1. 中間表現 (IR) からの翻訳
コンパイラ内部で使用される中間表現(ASTやSSA形式など)を基に、ターゲットコードを生成します。
2. メモリ管理
- 変数の割り当て
各変数や中間結果をレジスタ、スタック、またはヒープに割り当てます。 - アドレス計算
配列やポインタのようなデータ構造にアクセスする際のアドレス計算を正確に行います。
3. 命令選択
ターゲットプロセッサに適した命令セットを選択します。
4. 命令スケジューリング
プロセッサのパイプライン効率を最大化するため、命令の順序を調整します。
- 依存関係を考慮
ある命令の結果が次の命令で必要な場合、順序を維持します。
5. ジャンプと分岐の処理
条件分岐やループを適切に表現するために、ターゲットコードにジャンプ命令を埋め込みます。
6. 関数とサブルーチンの処理
関数呼び出しや戻り値の処理を行います。
- スタックフレームの管理
引数やローカル変数をスタックに割り当て、呼び出し先から復帰時に適切に解放。
結論
模索型言語のコード生成は、言語の動的な特性やランタイム要件を考慮するため、静的型付け言語よりも複雑になる場合があります。しかし、効率的なコード生成を行うことで、模索型言語の柔軟性を維持しながら、実行性能を最大化することが可能です。適切な中間表現の設計と最適化プロセスとの連携が、効果的なコード生成の鍵となります。
手続型言語のコンパイラのまとめ
手続型言語のコンパイラは、プログラムを機械語に変換する過程で、字句解析、構文解析、意味解析、最適化、コード生成を順に実行します。これにより、高水準なソースコードをコンピュータが理解・実行できる形式に変換します。特に最適化では、プログラムの実行効率や資源利用の向上が図られます。
アクチュエーター
アクチュエーターの説明として、適切なものはどれか。
ア 与えられた目標値と、センサーから得られた制御量を比較し、制御量を目標値に一致させるように操作量を出力する。
イ 位置、角度、速度、加速度、力、温度などを検出し、電気的な情報に変換する。
ウ エネルギー源からのパワーを、回転、直進などの動きに変換する。
ェ マイクロフォン、センサーなどが出力する微小な電気信号を増幅する。
引用:情報処理安全確保支援士試験 令和6年 秋 午前Ⅰ問8
解答
ウ
アクチュエーターの概要
アクチュエーター (Actuator) は、エネルギーを動力に変換する装置で、機械的な動作を行うための部品です。
例えば、モーターやシリンダーがこれに該当し、以下のような動きを実現します。
- 回転運動:電動モーターがエネルギーを回転動力に変換する。
- 直線運動:油圧シリンダーや空気圧シリンダーがエネルギーを直線運動に変換する。
アクチュエーターは、ロボットや機械制御システムで、目的の動作を実現する役割を担います。
各選択肢の検討
ア:与えられた目標値と、センサーから得られた制御量を比較し、制御量を目標値に一致させるように操作量を出力する。
- これはコントローラー(制御器)の役割です。PID制御器などが該当します。
- アクチュエーターは動作を実現するものであり、目標値の比較や操作量の計算は行いません。
イ:位置、角度、速度、加速度、力、温度などを検出し、電気的な情報に変換する。
- これはセンサーの説明です。 例えば、温度を検知するサーミスタや位置を測定するエンコーダーが該当します。
- アクチュエーターは物理的な動作を生成する役割であり、データの検出や変換は行いません。
ウ:エネルギー源からのパワーを、回転、直進などの動きに変換する。
- アクチュエーターの正確な説明です。
- 電気エネルギーを機械的運動に変える「モーター」
- 圧力エネルギーを直線運動に変える「シリンダー」 などが典型的なアクチュエーターです。
エ:マイクロフォン、センサーなどが出力する微小な電気信号を増幅する。
- これはアンプ(増幅器)の説明です。
- アクチュエーターは信号の増幅ではなく、物理的動作を担います。
アクチュエーターのまとめ
アクチュエーターは、エネルギー(電気、油圧、空気圧など)を回転や直進といった機械的な動きに変換する装置です。ロボットや自動車、産業機器などで使用され、モーターや油圧シリンダーなどが代表例です。センサーや制御装置と連携し、システム全体の動作を実現する重要な役割を担います。
帯域幅の計算方法
800 × 600 ピクセル、24ビットカラーで30フレーム/秒の動画像の配信に最小限必要な帯域幅はおよそ幾らか。ここで、通信時にデータ圧縮は行わないおのとする。
ア 350 k ビット/秒
イ 3.5 M ビット/秒
ウ 35 M ビット/秒
エ 350 M ビット/秒
引用:情報処理安全確保支援士試験 令和6年 秋 午前Ⅰ問9
解答
エ
帯域幅の計算手順
- 1フレームあたりのデータ量を計算
- 動画の解像度:800 × 600 ピクセル
- 1ピクセルのデータ量:24ビット(フルカラー=RGB各8ビット)
- 1フレームのデータ量(ビット単位): 800×600×24=11,520,000 ビット=11.52 Mビット
- 1秒あたりのフレーム数を考慮
- フレームレート:30フレーム/秒
- 1秒間に必要なデータ量:11.52 Mビット×30=345.6 Mビット
- 通信に必要な帯域幅を算出
- 通信では1秒間に345.6Mビットを転送する必要があるため、帯域幅は約345.6Mビット/秒です。よって、正解は、エの「350 M ビット/秒」になります。
帯域幅計算の公式
一般的に、帯域幅(必要データ転送速度)を求めるには次の式を使用します。
帯域幅(bps)= 解像度(横ピクセル × 縦ピクセル)×色深度(ビット/ピクセル)×フレームレート(フレーム/秒)
今回の条件を代入した具体的な計算式は以下の通りです。
帯域幅(bps)= 800 × 600 × 24 × 30 = 345.6 Mビット
データベースの設計
化粧品の製造を行っているA社では、販売代理店を通じて商品販売を行っている。今後の販売戦略に活用するために、次の三つの表を設計した。これらの表を用いるだけでは得ることのできない情報はどれか。
顧客
顧客ID 氏名 性別 生年月日 顧客 販売代理店別日別販売
販売代理店ID 日付 商品ID 販売数量 販売代理店別日別販売 商品購入
顧客ID 販売代理店ID 商品ID 購入数量 商品購入 ア 商品ごとの販売数量の日別差異
イ 性別ごとの売れ筋商品
ウ 販売代理店ごとの購入者数の日別差異
ェ 販売代理店ごとの売れ筋商品
引用:情報処理安全確保支援士試験 令和6年 秋 午前Ⅰ問10
解答
ウ
問題の解説
A社が設計した3つの表を基に、得られる情報と得られない情報を解析します。
表の構造と情報
- 顧客表
- 顧客IDをキーに、顧客の基本情報(氏名、性別、生年月日)を記録。
- 個々の顧客に関するデータを提供。
- 販売代理店別日別販売表
- 販売代理店ID、日付、商品IDをキーに、販売数量を記録。
- 日ごと、商品ごとの販売実績を記録するが、どの顧客が購入したかはわからない。
- 商品購入表
- 顧客ID、販売代理店ID、商品IDをキーに、購入数量を記録。
- 各顧客がどの販売代理店で何を購入したかの情報を提供。
選択肢の検討
ア:商品ごとの販売数量の日別差異
- 販売代理店別日別販売表を使えば、日付ごとに商品IDごとの販売数量を集計できます。 したがって、この情報は得られる。
イ:性別ごとの売れ筋商品
- 顧客表(性別情報)と商品購入表(購入情報)を結合することで、性別ごとの売れ筋商品を分析できます。 したがって、この情報は得られる。
ウ:販売代理店ごとの購入者数の日別差異
- 商品購入表には販売代理店ID、顧客ID、日付が記録されているため、これを集計することで購入者数を算出できます。
- しかし、「購入者数の日別差異」を求めるには、日ごとに異なる購入者数を明確にする必要があります。
- 日付ごとの購入者(顧客IDのユニーク数)が集計できない場合、表だけでは日別差異を算出できません。
- この分析には追加のロジックやプログラムが必要になるため、この情報は得られない。
エ:販売代理店ごとの売れ筋商品
- 商品購入表を使い、販売代理店IDごとに商品IDを集計することで、売れ筋商品を特定できます。 したがって、この情報は得られる。
結論
販売代理店ごとの購入者数の日別差異を求めるためには、ユニークな購入者の集計が必要ですが、与えられた表だけでは直接得ることができません。
まとめ
今回は、下記について説明しました。
- ページング方式
- コンパイラのコード生成
- アクチュエーター
- 帯域幅の計算方法
- データベースの設計
今回は、令和6年度秋期午前Ⅰ共通問題の問6から問10で出題された用語について説明しました。次回は、問11から問15について説明します。
これからも、Macのシステムエンジニアとして、日々、習得した知識や経験を発信していきますので、是非、ブックマーク登録してくれると嬉しいです!
それでは、次回のブログで!