跳转至

Batch.h

Go to the source code of this file.

Batch 检查是一种一次处理多个图像的功能。

ExampleClsRuntimeBatch.cpp示例展示了如何执行批量检查。 SAIGE VISION中的批量检查是一次处理多个图像的功能。 这使用更多的GPU内存。 此外,一次处理更多图像并不总是使其更快。 因此,有必要选择适当的Batch Size。

Batch 检查步骤

要执行批量检查,请按照以下步骤操作:

  • 创建句柄时设置Batch Size
  • 将多个图像数据加载到内存中
  • 调用Batch Infer API SaigeInferFromMultipleByteArray
  • 从每个结果句柄中检索并利用每个图像的检查结果

设置Batch Size

在创建句柄时设置 SaigeHandleConfig::batchSize 值并通过指定标志创建句柄。

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// ExampleClsRuntimeBatch.cpp:81

SaigeInferenceHandle handle = nullptr;
SaigeHandleConfig config;
config.batchSize = batchSize;
unsigned int handleFlags = SAIGE_SET_BATCH_SIZE;
if (optimize) {
    handleFlags |= SAIGE_OPTIMIZE_HANDLE;
}
retval = SaigeCreateInferenceHandle(&handle, kProjectTypeCLS, trainedModelPath.c_str(),
                                    deviceIndex, &config, handleFlags);
if (retval < 0) {
    std::cerr << "SaigeCreateInferenceHandle failed - " << SaigeStrError(retval) << std::endl;
    return retval;
}

加载图像

在此示例中,读取指定的 dataDir 路径下的所有 .png 文件并将其存储在 imagePaths 中。 然后,应用程序代码根据 batchSize 捆绑并处理这些图像。 也就是说,在此示例中,batchSize >= numOfImages。

以下代码是按 batchSize 划分的整个图像列表进行检查的循环的开始部分。 将每次迭代对应的图像加载到 ucBatchImageData 中。

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
// ExampleClsRuntimeBatch.cpp:214

unsigned char** ucBatchImageData = new unsigned char*[batchSize];
for (int i = 0; i < batchSize; ++i) {
    ucBatchImageData[i] = nullptr;
}

int numIter = (int)std::ceil((float)imagePaths.size() / (float)batchSize);
int numFinalImages = imagePaths.size() % batchSize;
if (numFinalImages == 0) numFinalImages = batchSize;
int numBatch = batchSize;

// start iteration
for (int iter = 0; iter < numIter; ++iter) {
    if (iter == numIter - 1) {
        numBatch = numFinalImages;
    }
    // 이미지 데이터 메모리를 해제합니다. (루프일관성)
    clearImageBatch(ucBatchImageData, batchSize);

    // 이미지 batch를 생성합니다.
    int w_batch = 0, h_batch = 0, c_batch = 0, type_batch = -1;
    bool invalid_batch = false;
    for (int i = 0; i < numBatch; ++i) {
        invalid_batch = false;
        int img_idx = i + iter * batchSize;
        ucBatchImageData[i] =
            (unsigned char*)SaigeGetImageData(imagePaths[img_idx].c_str(), &w, &h, &c, &type);
        if (i == 0) {
            w_batch = w;
            h_batch = h;
            c_batch = c;
            type_batch = type;
        }
        if (ucBatchImageData[i] == nullptr) {
            // 로드에 실패한 이미지가 있으면 다음 배치로 넘어갑니다.
            invalid_batch = true;
            std::cerr << "SaigeGetImageData() failed - " << imagePaths[img_idx] << std::endl;
            break;
        }
        if (w != w_batch || h != h_batch || c != c_batch) {
            // 한 배치 내의 이미지 크기는 모두 같아야 합니다.
            invalid_batch = true;
            std::cerr << "Image sizes in a same batch should be same." << std::endl;
            break;
        }
    }

调用Batch Infer API

调用Batch Infer API,SaigeInferFromMultipleByteArray 函数。

275
276
277
278
279
280
281
282
283
// ExampleClsRuntimeBatch.cpp:277

retval = SaigeInferFromMultipleByteArray(
    handle, numBatch, (const unsigned char**)ucBatchImageData, w, h, imageFlag, results);
if (retval < 0) {
    std::cerr << "SaigeInferFromByteArray() failed - " << SaigeStrError(retval)
              << std::endl;
    continue;
}

检索检查结果

调用Batch Infer API后,从每个结果句柄中检索每个图像的检查结果。 因此,结果句柄的数量必须至少为 numOfImages。

288
289
290
291
292
293
294
295
296
297
298
299
300
// ExampleClsRuntimeBatch.cpp:290

for (int i = 0; i < numBatch; ++i) {  // DEFAULT
    retval = SaigeGetInferenceResultScore(results[i], scores[i].data(), true);
    if (retval < 0) {
        std::cerr << "SaigeGetInferenceResultScore() failed - " << SaigeStrError(retval)
                  << std::endl;
        clearImageBatch(ucBatchImageData, batchSize);
        delete[] ucBatchImageData;
        SaigeDestroyInferenceHandle(handle);
        clearResults(results, batchSize);
        return retval;
    }

Batch Size 和 numOfImages 之间的关系

设置的 Batch Size 和实际输入到 SaigeInferFromMultipleByteArray 函数的图像数量不必匹配。

Batch Size 是 GPU 上同时处理的图像数量。

因此,如果输入到 Batch Infer API 的图像数量 numOfImages 大于 Batch Size,则操作将分成多个操作。 此外,如果输入图像的数量少于 Batch Size,则会浪费 GPU 资源。 因此,Batch Size 是一个重要的调整因素, 应谨慎设置。

也就是说,根据应用程序的特性,可以设置不同的输入图像数量 numOfImages。 例如,有时一次收集和处理多个图像, 有时需要尽快获得检查结果。

通常,为了提高检查的吞吐量,建议尽可能将 batchSize 设置得更大。 相反,如果检查的延迟很重要,则建议尽快调用检查 API, 而不必等待收集检查图像。