虽然脚本可能是有效的 JavaScript,没有逻辑错误,并代表服务器的一组有效指令,但在并行化和执行计算时,结果对象可能太大、太多或计算时间太长。在这种情况下,您将收到一个错误,指出该算法无法缩放。这些错误通常是最难诊断和解决的。此类错误的示例包括:
警告:存在配额限制以确保整个地球引擎社区的计算资源的可用性。试图通过使用多个 Google 帐户来规避配额限制是违反 地球引擎服务条款的。
改进代码的可伸缩性将使您更快地获得结果,并提高所有用户的计算资源的可用性。下面将讨论每种类型的错误,然后简要介绍reduceRegion()
,这是一个因能够导致每种类型的缩放错误而臭名昭著的常用函数。
reduceRegion()
虽然reduceRegion()
贪婪地消耗足够的像素来触发各种令人兴奋的错误,但也有用于控制计算的参数,因此您可以克服错误。例如,考虑以下不可取的减少:
错误— 此代码不起作用!
var absurdComputation = ee.Image(1).reduceRegion({
reducer: 'count',
geometry: ee.Geometry.Rectangle([-180, -90, 180, 90], null, false),
scale: 100,
});
// Error: Image.reduceRegion: 太多像素用于计算了,所以超出了像素,建议缩小scale,也就是分辨率你得调大
// Found 80300348117, but only 10000000 allowed.
print(absurdComputation);
这个例子只是为了演示。此错误的目的是询问您是否真的要减少 80300348117(即 800亿)像素。如果没有,相应地增加scale
(以米为单位的像素大小),或设置bestEffort
为 true,以自动重新计算更大的比例。这样可以最大限度的获取你想要的图像,在不超出计算范围的前提下!!!
假设您在计算中需要所有这些像素。如果是这样,您可以增加 maxPixels
参数以允许计算成功。但是,Earth Engine 需要一些时间来完成计算。因此,可能会抛出“计算超时”错误:
不好——不要这样做!
var ridiculousComputation = ee.Image(1).reduceRegion({
reducer: 'count',
geometry: ee.Geometry.Rectangle([-180, -90, 180, 90], null, false),
scale: 100,
maxPixels: 1e11
});
// Error: 计算超时
print(ridiculousComputation);
这个错误意味着地球引擎在停止计算之前等待了大约五分钟。导出允许 Earth Engine 在具有更长允许运行时间(但不能有更多内存)的环境中执行计算。由于返回值reduceRegion()
是字典,因此您可以使用字典来设置具有空几何的特征的属性:
好- 使用Export
!
Export.table.toDrive({
collection: ee.FeatureCollection([
ee.Feature(null, ridiculousComputation)
]),
description: 'ridiculousComputation',
fileFormat: 'CSV'
});
此错误的“聚合”部分指的是分布在多台机器上的操作(例如跨越多个瓦片的减少)。Earth Engine 有限制,以防止同时运行太多这样的聚合。在此示例中,“并发聚合过多”错误是由映射内的减少触发的:
不好——不要这样做!
var collection = ee.ImageCollection('LANDSAT/LT05/C01/T1')
.filterBounds(ee.Geometry.Point([-123, 43]));
var terribleAggregations = collection.map(function(image) {
return image.set(image.reduceRegion({
reducer: 'mean',
geometry: image.geometry(),
scale: 30,
maxPixels: 1e9
}));
});
// Error: Quota exceeded: 并发聚合过多。
print(terribleAggregations);
假设这段代码的目的是获取每个图像的图像统计信息,一个可能的解决方案是Export
结果。例如,使用ImageCollection
,FeatureCollection
可以将与图像关联的元数据导出为表格:
好- 使用Export
!
Export.table.toDrive({
collection: terribleAggregations,
description: 'terribleAggregations',
fileFormat: 'CSV'
});
您的算法在 Earth Engine 中并行化的一种方法是将输入拆分为瓦片,在每个瓦片上单独运行相同的计算,然后组合结果。因此,计算输出图块所需的所有输入都必须适合内存。例如,当输入是具有许多波段的图像时,如果所有波段都用于计算,则最终可能会占用大量内存。为了演示,这个例子通过强制(不必要地)整个图像集合到一个图块中使用了太多内存:
不好——不要这样做!
var memoryHog = ee.ImageCollection('LANDSAT/LT05/C01/T1')
.toArray()
.arrayReduce(ee.Reducer.mean(), [0])
.arrayProject([1])
.arrayFlatten([['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'QA']])
.reduceRegion({
reducer: 'mean',
geometry: ee.Geometry.Point([-122.27, 37.87]).buffer(1000),
scale: 1,
bestEffort: true,
});
// Error: 用户内从超出
print(memoryHog);
这段非常糟糕的代码展示了一个不使用数组的原因,除非您确实需要(另请参阅“避免不必要地转换类型”部分)。当该集合转换为一个巨大的数组时,该数组必须一次全部加载到内存中。因为它是一个很长的时间序列图像,所以数组很大并且主机不适合计算如此巨大的内存。
一种可能的解决方案是将tileScale
参数设置为更高的值。较高的 tileScale 值会导致图块缩小 1 倍 tileScale^2
。例如,以下允许计算成功:
var smallerHog = ee.ImageCollection('LANDSAT/LT05/C01/T1')
.toArray()
.arrayReduce(ee.Reducer.mean(), [0])
.arrayProject([1])
.arrayFlatten([['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'QA']])
.reduceRegion({
reducer: 'mean',
geometry: ee.Geometry.Point([-122.27, 37.87]).buffer(1000),
scale: 1,//这个像素点也可以扩大
bestEffort: true,//这个参数默认就是最好的
tileScale: 16//添加这个可以导致图块缩小一倍所以效率极大提升
});
print(smallerHog);
但是,更受欢迎的解决方案是不要不必要地使用数组,因此您根本不需要摆弄tileScale
:
好——避免数组!从一开始就减少.toArray()
var okMemory = ee.ImageCollection('LANDSAT/LT05/C01/T1')
.mean()
.reduceRegion({
reducer: 'mean',
geometry: ee.Geometry.Point([-122.27, 37.87]).buffer(1000),
scale: 1,
bestEffort: true,
});
print(okMemory);
除非有必要解决内存错误,否则不应将tileScale
较小的切片设置为也会导致较大的并行化内存消耗。
您可能会遇到类似于以下内容的错误:
发生内部错误。
如果您收到此错误,请单击控制台中显示的“报告错误”链接。您还可以通过“帮助” 按钮发送反馈。此错误可能是由于脚本中的逻辑错误导致的,这些错误只会在运行时变得明显,或者是 Earth Engine 的内部工作问题。在任何一种情况下,错误都是无意义的,应该报告以便修复。
内部错误包括一个request
ID,如下所示:
(request: 4b14e62b-f73f-49cc-9cf7-901cad12058b)
这些字符串充当唯一标识符,帮助地球引擎团队识别特定问题。请在错误报告中包含此字符串。