SageMaker 推理的费用包括四类,实时推理、批量转换、异步推理和无服务器推理:
real-time inference
: 满足在线、低延迟或高吞吐量要求的实时推理
batch transform
: 用于离线、计划处理以及不需要持久端点时的批量转换
asynchronous inference
: 当您有大量负载且处理时间较长并且想要对请求进行排队时进行异步推理
serverless inference
: 当您具有间歇性或不可预测的流量模式并且可以容忍冷启动时进行无服务器推理
当创建终端节点时,SageMaker 会将 EBS存储卷附加到托管该终端节点的EC2, 对于所有不配备 SSD 存储的实例类型都是如此。由于 d*
实例类型附带 NVMe SSD 存储,因此 SageMaker 不会将 EBS 存储卷附加到这些 ML 计算实例。请参阅主机实例存储卷
了解 SageMaker 为单个终端节点和多模型终端节点的每种实例类型附加的存储卷的大小。
SageMaker Real-time
Endpoints的成本基于endpoint运行时每个实例消耗的每个实例小时、每月 GB 的预配置存储(EBS 卷)的成本,以及处理进出endpoint instance的 GB 数据的信息。在 Cost Explorer 中,可以通过按usage type
来分类筛选。
这些usage type
的名称结构如下:
REGION-Host:instanceType
(例如,USE1-Host:ml.c5.9xlarge
)REGION-Host:VolumeUsage.gp2
(例如,USE1-Host:VolumeUsage.gp2
)REGION-Hst:Data-Bytes-In
(例如,USE2-Hst:Data-Bytes-In
)REGION-Hst:Data-Bytes-Out
(例如,USW2-Hst:Data-Bytes-Out)
如下图所示,按使用类型过滤Host:
将显示帐户中实时托管使用类型的列表。
<img src="https://pingfan.s3-us-west-2.amazonaws.com/pic6/31acol.jpg" alt="img">
可以选择特定使用类型,也可以选择全选并选择应用以显示 SageMaker 实时托管使用的成本明细。还可以应用其他过滤器,例如帐号、EC2 实例类型、成本分配标签、区域等。以下屏幕截图显示了所选托管使用类型的成本和使用情况图表。
<img src="https://pingfan.s3-us-west-2.amazonaws.com/pic6/9aq3s4.jpg" alt="img">
此外,可以使用实例类型筛选器探索与一个或多个托管实例相关的成本。以下屏幕截图显示了托管实例 ml.p2.xlarge 的成本和使用情况细分。
<img src="https://pingfan.s3-us-west-2.amazonaws.com/pic6/h2eb4a.jpg" alt="img">
同样,可以通过使用类型来筛选传入和传出的 GB 数据的成本,如以下屏幕截图所示。
可以从 AWS CUR 获取资源级别信息,例如终端节点 ARN、终端节点实例类型、每小时实例费率、每日使用时间等:
SELECT
bill_payer_account_id,
line_item_usage_account_id,
line_item_resource_id AS endpoint_arn,
line_item_usage_type,
DATE_FORMAT((line_item_usage_start_date),'%Y-%m-%d') AS day_line_item_usage_start_date,
SUM(CAST(line_item_usage_amount AS DOUBLE)) AS sum_line_item_usage_amount,
line_item_unblended_rate,
SUM(CAST(line_item_unblended_cost AS DECIMAL(16,8))) AS sum_line_item_unblended_cost,
line_item_blended_rate,
SUM(CAST(line_item_blended_cost AS DECIMAL(16,8))) AS sum_line_item_blended_cost,
line_item_line_item_description,
line_item_line_item_type
FROM
customer_all
WHERE
line_item_usage_start_date >= date_trunc('month',current_date - interval '3' month)
AND line_item_product_code = 'AmazonSageMaker'
AND line_item_line_item_type IN ('DiscountedUsage', 'Usage', 'SavingsPlanCoveredUsage')
AND line_item_usage_type like '%Host%'
AND line_item_operation = 'RunInstance'
AND bill_payer_account_id = 'xxxxxxxxxxxx'
GROUP BY
bill_payer_account_id,
line_item_usage_account_id,
line_item_resource_id,
line_item_usage_type,
line_item_unblended_rate,
line_item_blended_rate,
line_item_line_item_type,
DATE_FORMAT((line_item_usage_start_date),'%Y-%m-%d'),
line_item_line_item_description
ORDER BY
line_item_resource_id, day_line_item_usage_start_date
运行查询所获得的结果:
<img src="https://pingfan.s3-us-west-2.amazonaws.com/pic6/z43cin.png" alt="img">
查询结果显示,mme-xgboost-housing
使用 ml.x4.xlarge 实例,连续多天 24 小时运行。实例费率为 0.24 美元/小时,运行 24 小时的每日费用为 5.76 美元。
AWS CUR 结果可以帮助识别每个账户中连续几天运行的终端节点,以及每月成本最高的终端节点。以帮助决定是否可以删除非生产账户中的终端节点以节省成本。
在Cost Explorer里,只能看到总的Hst:Data-Bytes-Out/In
值,如果想区分出哪个endpoint产生的,即使打了标签也区分不出来。
可行的思路是根据调用的次数(Invokation count)来统计每个endpoint的访问量。在cloudwatch metric中,SageMaker
空间下有相应的调用指标:
也可以使用脚本拉取每个endpoint的调用次数,参考: https://github.com/vinayak-shanawad/AWS-SageMaker-Examples/blob/main/08_Monitor_SM_CloudWatch_Metrics/sm_cloudwatch_metrics.py
https://medium.com/mlearning-ai/monitoring-and-saving-sagemaker-inference-expenses-f6795a9193ab
统计每个endpoint一小时内调用次数总和:
import boto3
from datetime import datetime, timedelta
from collections import Counter
counter = Counter()
sm_client = boto3.client('sagemaker')
# 列出所有端点
response = sm_client.list_endpoints(
SortBy='Name',
SortOrder='Ascending',
MaxResults=100,
StatusEquals='InService'
)
for i in response['Endpoints']:
print("EndpointName", i['EndpointName'])
# 检索端点详细信息
des_ep_response = sm_client.describe_endpoint(EndpointName=i['EndpointName'])
print(des_ep_response)
variant_name = des_ep_response["ProductionVariants"][0]["VariantName"] # variant-name-1
# 计算端点创建时间与当前日期之间的差值
# start_time = des_ep_response["CreationTime"]
# print(type(start_time))
# print(start_time)
end_time = datetime.utcnow()
start_time = end_time - timedelta(hours=1)
print(start_time, end_time)
cw_client = boto3.client('cloudwatch')
# Define the metric parameters
metric_name = 'Invocations'
statistics = ['Sum']
# Retrieve the metric data
metrics_response = cw_client.get_metric_statistics(
Namespace='AWS/SageMaker',
MetricName=metric_name,
Dimensions=[
{
'Name': 'EndpointName',
'Value': i['EndpointName']
},
{
'Name': 'VariantName',
'Value': variant_name
}
],
StartTime=start_time,
EndTime=end_time,
Period=300,
Statistics=statistics
)
print(metrics_response)
# Print the metric data
datapoints = metrics_response['Datapoints']
total_invocations = 0
if datapoints:
for j in range(len(datapoints)):
# Get the latest data point
print(datapoints[j]['Timestamp'], datapoints[j]['Sum'])
total_invocations += datapoints[j]['Sum']
else:
print("No data available")
print("Endpoint Name", i['EndpointName'], ", Total Invokations", total_invocations)
counter[i['EndpointName']] = total_invocations
for k in sorted(counter, key=counter.get, reverse=True):
print(k, "一小时的调用次数:", counter[k])