Hikaru's notes

A collection of notes and resources

View the Project on GitHub HikaruMizoe/notes

4.2 インフラストラクチャとコストをモニタリングおよび最適化する

タスクステートメント

インフラストラクチャとコストをモニタリングおよび最適化する

対象知識

ML インフラストラクチャの主要なパフォーマンスメトリクス

使用率(Utilization)

スループット(Throughput)

可用性(Availability)

スケーラビリティ(Scalability)

耐障害性(Fault Tolerance)

レイテンシーとパフォーマンスの問題をトラブルシューティングするためのモニタリングツールとオブザーバビリティツール

AWS X-Ray

Amazon CloudWatch Lambda Insights

Amazon CloudWatch Logs Insights

AWS CloudTrail を使用した再トレーニングアクティビティのログ記録、モニタリング、呼び出しの方法

CloudTrail の機能

SageMaker でのCloudTrail活用

インスタンスタイプの違いとパフォーマンスへの影響

メモリ最適化(R ファミリー)

コンピューティング最適化(C ファミリー)

汎用(M ファミリー)

推論最適化(Inf, G ファミリー)

コスト分析ツールの機能

AWS Cost Explorer

AWS Billing and Cost Management

AWS Trusted Advisor

コスト追跡とコスト配分の手法

リソースのタグ付け

対象スキル

1. リソースのトラブルシューティングと分析のためにツールを設定して使用する

CloudWatch Logs の設定

import boto3

logs = boto3.client('logs')

# ロググループの作成
logs.create_log_group(
    logGroupName='/aws/sagemaker/TrainingJobs'
)

# 保持期間の設定
logs.put_retention_policy(
    logGroupName='/aws/sagemaker/TrainingJobs',
    retentionInDays=30
)

# ログストリームの作成
logs.create_log_stream(
    logGroupName='/aws/sagemaker/TrainingJobs',
    logStreamName='job-2025-01-01'
)

CloudWatch Alarms の設定

cloudwatch = boto3.client('cloudwatch')

# CPU使用率のアラーム
cloudwatch.put_metric_alarm(
    AlarmName='HighCPUUtilization',
    ComparisonOperator='GreaterThanThreshold',
    EvaluationPeriods=2,
    MetricName='CPUUtilization',
    Namespace='AWS/SageMaker',
    Period=300,
    Statistic='Average',
    Threshold=80.0,
    ActionsEnabled=True,
    AlarmActions=['arn:aws:sns:us-east-1:123456789012:alerts'],
    Dimensions=[
        {
            'Name': 'EndpointName',
            'Value': 'production-endpoint'
        }
    ]
)

2. CloudTrail 証跡を作成する

import boto3

cloudtrail = boto3.client('cloudtrail')

# 証跡の作成
response = cloudtrail.create_trail(
    Name='ml-audit-trail',
    S3BucketName='my-cloudtrail-bucket',
    IncludeGlobalServiceEvents=True,
    IsMultiRegionTrail=True,
    EnableLogFileValidation=True,
    Tags=[
        {'Key': 'Environment', 'Value': 'Production'},
        {'Key': 'Purpose', 'Value': 'ML-Audit'}
    ]
)

# ログ記録の開始
cloudtrail.start_logging(Name='ml-audit-trail')

# イベントセレクタの設定(SageMaker イベントのみ)
cloudtrail.put_event_selectors(
    TrailName='ml-audit-trail',
    EventSelectors=[
        {
            'ReadWriteType': 'All',
            'IncludeManagementEvents': True,
            'DataResources': [
                {
                    'Type': 'AWS::SageMaker::TrainingJob',
                    'Values': ['arn:aws:sagemaker:*:*:training-job/*']
                },
                {
                    'Type': 'AWS::SageMaker::Endpoint',
                    'Values': ['arn:aws:sagemaker:*:*:endpoint/*']
                }
            ]
        }
    ]
)

3. パフォーマンスメトリクスをモニタリングするためにダッシュボードを設定する

CloudWatch ダッシュボード

import json
import boto3

cloudwatch = boto3.client('cloudwatch')

dashboard_body = {
    "widgets": [
        {
            "type": "metric",
            "properties": {
                "metrics": [
                    ["AWS/SageMaker", "CPUUtilization", {"stat": "Average"}],
                    [".", "MemoryUtilization", {"stat": "Average"}],
                    [".", "DiskUtilization", {"stat": "Average"}]
                ],
                "period": 300,
                "stat": "Average",
                "region": "us-east-1",
                "title": "Resource Utilization",
                "yAxis": {"left": {"min": 0, "max": 100}}
            }
        },
        {
            "type": "metric",
            "properties": {
                "metrics": [
                    ["AWS/SageMaker", "ModelLatency", {"stat": "Average"}],
                    [".", "Invocations", {"stat": "Sum", "yAxis": "right"}]
                ],
                "period": 300,
                "stat": "Average",
                "region": "us-east-1",
                "title": "Performance Metrics",
                "yAxis": {
                    "left": {"label": "Latency (ms)"},
                    "right": {"label": "Invocations"}
                }
            }
        }
    ]
}

cloudwatch.put_dashboard(
    DashboardName='ML-Performance-Dashboard',
    DashboardBody=json.dumps(dashboard_body)
)

QuickSight ダッシュボード(高度な分析)

import boto3

quicksight = boto3.client('quicksight')

# データソースの作成
response = quicksight.create_data_source(
    AwsAccountId='123456789012',
    DataSourceId='sagemaker-metrics-datasource',
    Name='SageMaker Metrics',
    Type='ATHENA',
    DataSourceParameters={
        'AthenaParameters': {
            'WorkGroup': 'primary'
        }
    },
    Permissions=[
        {
            'Principal': 'arn:aws:iam::123456789012:role/QuickSightRole',
            'Actions': [
                'quicksight:DescribeDataSource',
                'quicksight:PassDataSource'
            ]
        }
    ]
)

4. インフラストラクチャをモニタリングする(EventBridge イベントの使用)

import boto3
import json

events = boto3.client('events')

# エンドポイント状態変更イベントのルール
events.put_rule(
    Name='endpoint-state-change',
    EventPattern=json.dumps({
        'source': ['aws.sagemaker'],
        'detail-type': ['SageMaker Endpoint State Change'],
        'detail': {
            'EndpointStatus': ['Failed', 'OutOfService']
        }
    }),
    State='ENABLED',
    Description='Alert on endpoint state changes'
)

# SNS トピックをターゲットに設定
events.put_targets(
    Rule='endpoint-state-change',
    Targets=[
        {
            'Id': '1',
            'Arn': 'arn:aws:sns:us-east-1:123456789012:alerts',
            'InputTransformer': {
                'InputPathsMap': {
                    'endpoint': '$.detail.EndpointName',
                    'status': '$.detail.EndpointStatus'
                },
                'InputTemplate': '"Endpoint <endpoint> is now <status>"'
            }
        }
    ]
)

5. インスタンスファミリーとサイズを適正化する

SageMaker Inference Recommender

from sagemaker.model import Model
from sagemaker.predictor import Predictor

model = Model(
    image_uri=container,
    model_data=f's3://{bucket}/model.tar.gz',
    role=role
)

# Inference Recommender ジョブの実行
recommender_job = model.right_size(
    sample_payload_url=f's3://{bucket}/sample-payload.jsonl',
    supported_instance_types=['ml.m5.large', 'ml.m5.xlarge', 'ml.c5.large', 'ml.c5.xlarge'],
    framework='pytorch',
    job_name='model-sizing-job'
)

# 推奨結果の取得
recommendations = recommender_job.describe()
print(recommendations)

AWS Compute Optimizer

import boto3

compute_optimizer = boto3.client('compute-optimizer')

# 推奨事項の取得
response = compute_optimizer.get_ec2_instance_recommendations(
    instanceArns=[
        'arn:aws:ec2:us-east-1:123456789012:instance/i-xxxxx'
    ]
)

for recommendation in response['instanceRecommendations']:
    print(f"Current: {recommendation['currentInstanceType']}")
    for option in recommendation['recommendationOptions']:
        print(f"Recommended: {option['instanceType']}")
        print(f"Expected savings: {option['savingsOpportunity']}")

6. レイテンシーとスケーリングの問題をモニタリングおよび解決する

レイテンシー分析

import boto3
from datetime import datetime, timedelta

cloudwatch = boto3.client('cloudwatch')

# レイテンシーメトリクスの取得
response = cloudwatch.get_metric_statistics(
    Namespace='AWS/SageMaker',
    MetricName='ModelLatency',
    Dimensions=[
        {'Name': 'EndpointName', 'Value': 'production-endpoint'},
        {'Name': 'VariantName', 'Value': 'AllTraffic'}
    ],
    StartTime=datetime.now() - timedelta(hours=24),
    EndTime=datetime.now(),
    Period=300,
    Statistics=['Average', 'Maximum', 'p99']
)

# 分析
datapoints = response['Datapoints']
avg_latency = sum(d['Average'] for d in datapoints) / len(datapoints)
max_latency = max(d['Maximum'] for d in datapoints)

print(f"Average Latency: {avg_latency}ms")
print(f"Maximum Latency: {max_latency}ms")

# レイテンシーが高い場合の対応
if avg_latency > 100:  # 100ms閾値
    print("Consider scaling up or using faster instance types")

7. コストモニタリングのためにインフラストラクチャを準備する(タグ付け戦略の適用)

タグ付け戦略

import boto3

sagemaker = boto3.client('sagemaker')

# トレーニングジョブにタグ付け
response = sagemaker.create_training_job(
    TrainingJobName='tagged-training-job',
    RoleArn=role,
    AlgorithmSpecification={...},
    InputDataConfig=[...],
    OutputDataConfig={...},
    ResourceConfig={...},
    Tags=[
        {'Key': 'Project', 'Value': 'CustomerChurn'},
        {'Key': 'Environment', 'Value': 'Production'},
        {'Key': 'CostCenter', 'Value': 'ML-Team'},
        {'Key': 'Owner', 'Value': 'data-science-team'}
    ]
)

# エンドポイントにタグ付け
sagemaker.create_endpoint(
    EndpointName='production-endpoint',
    EndpointConfigName='endpoint-config',
    Tags=[
        {'Key': 'Project', 'Value': 'CustomerChurn'},
        {'Key': 'Environment', 'Value': 'Production'},
        {'Key': 'CostCenter', 'Value': 'ML-Team'}
    ]
)

8. コストとパフォーマンスに関係する容量の懸念をトラブルシューティングする

プロビジョニング済み同時実行

# Lambda のプロビジョニング済み同時実行
lambda_client = boto3.client('lambda')

lambda_client.put_provisioned_concurrency_config(
    FunctionName='ml-inference-function',
    Qualifier='$LATEST',
    ProvisionedConcurrentExecutions=10
)

サービスクォータの確認と引き上げリクエスト

import boto3

service_quotas = boto3.client('service-quotas')

# 現在のクォータを確認
response = service_quotas.get_service_quota(
    ServiceCode='sagemaker',
    QuotaCode='L-D9C0F13C'  # ml.p3.2xlarge インスタンス数
)

print(f"Current quota: {response['Quota']['Value']}")

# クォータ引き上げリクエスト
request = service_quotas.request_service_quota_increase(
    ServiceCode='sagemaker',
    QuotaCode='L-D9C0F13C',
    DesiredValue=20.0
)

9. 適切なコスト管理ツールを使用してコストを最適化し、コストクォータを設定する

AWS Budgets の設定

import boto3

budgets = boto3.client('budgets')

# 予算の作成
response = budgets.create_budget(
    AccountId='123456789012',
    Budget={
        'BudgetName': 'ML-Monthly-Budget',
        'BudgetLimit': {
            'Amount': '10000',
            'Unit': 'USD'
        },
        'TimeUnit': 'MONTHLY',
        'BudgetType': 'COST',
        'CostFilters': {
            'Service': ['Amazon SageMaker']
        }
    },
    NotificationsWithSubscribers=[
        {
            'Notification': {
                'NotificationType': 'ACTUAL',
                'ComparisonOperator': 'GREATER_THAN',
                'Threshold': 80.0,
                'ThresholdType': 'PERCENTAGE'
            },
            'Subscribers': [
                {
                    'SubscriptionType': 'EMAIL',
                    'Address': 'ml-team@example.com'
                }
            ]
        }
    ]
)

Cost Explorer API の使用

import boto3
from datetime import datetime, timedelta

ce = boto3.client('ce')

# 過去30日間のコスト取得
response = ce.get_cost_and_usage(
    TimePeriod={
        'Start': (datetime.now() - timedelta(days=30)).strftime('%Y-%m-%d'),
        'End': datetime.now().strftime('%Y-%m-%d')
    },
    Granularity='DAILY',
    Metrics=['UnblendedCost'],
    GroupBy=[
        {'Type': 'DIMENSION', 'Key': 'SERVICE'},
        {'Type': 'TAG', 'Key': 'Project'}
    ]
)

# コスト分析
for result in response['ResultsByTime']:
    print(f"Date: {result['TimePeriod']['Start']}")
    for group in result['Groups']:
        service = group['Keys'][0]
        project = group['Keys'][1]
        cost = group['Metrics']['UnblendedCost']['Amount']
        print(f"  {service} - {project}: ${cost}")

10. 購入オプションを選択することにより、インフラストラクチャコストを最適化する

スポットインスタンス

from sagemaker.estimator import Estimator

# トレーニングでスポットインスタンス使用
estimator = Estimator(
    image_uri=container,
    role=role,
    instance_count=2,
    instance_type='ml.p3.2xlarge',
    use_spot_instances=True,
    max_run=3600,  # 最大実行時間
    max_wait=7200  # スポット中断時の待機時間
)

estimator.fit(training_data)

リザーブドインスタンス / SageMaker Savings Plans

# AWS CLIでSavings Planを購入
aws savingsplans purchase-savings-plan \
    --savings-plan-offering-id offering-xxxxx \
    --commitment 100  # 1時間あたり$100のコミットメント

コスト最適化のベストプラクティス

  1. 適切なインスタンスタイプの選択
    • Inference Recommender を活用
    • 過剰なスペックを避ける
  2. オートスケーリングの活用
    • 需要に応じたスケーリング
    • 最小/最大インスタンス数の設定
  3. スポットインスタンスの活用
    • トレーニングジョブで最大90%削減
    • 中断許容可能なワークロード
  4. リザーブドインスタンス / Savings Plans
    • 長期稼働のエンドポイント
    • 最大72%のコスト削減
  5. 不要なリソースの削除
    • 未使用のエンドポイント停止
    • 古いモデルアーティファクトの削除

関連リンク