ncnn gpt - YingkunZhou/transfer-learning GitHub Wiki

ex.extract(output_names[0], output_tensor);

这段代码是一个名为 Extractor::extract 的函数,用于在 ncnn 框架中从网络中提取特征。

函数的参数包括 blob_index、feat 和 type。blob_index 表示要提取特征的 blob 索引,feat 是用于存储提取得到的特征的 Mat 对象,type 表示特征的类型。

代码的主要逻辑如下:

  1. 首先,检查 blob_index 是否有效,即是否在 d->blob_mats 的范围内。如果不在范围内,则返回错误码 -1。
  2. 接下来,保存当前的 KMP(OpenMP)块时间和 denormals 刷新设置,并根据 d->opt.openmp_blocktime 和 d->opt.flush_denormals 设置新的值。
  3. 定义变量 ret,用于存储函数的返回值。
  4. 如果 d->blob_mats[blob_index] 的维度为 0,表示该 blob 还没有被计算,需要根据网络结构进行计算。
  5. 如果 d->opt.use_local_pool_allocator 为真,表示使用本地内存池分配器,需要设置相关的内存分配器。如果 d->opt.blob_allocator 为空,则使用网络的本地 blob 分配器;如果 d->opt.workspace_allocator 为空,则使用网络的本地工作空间分配器。
  6. 如果支持 Vulkan 计算,并且 d->opt.use_vulkan_compute 为真,表示使用 Vulkan 进行计算。在这种情况下,需要设置 Vulkan 相关的内存分配器和命令队列。
  • 如果 d->opt.use_image_storage 为真,表示使用 VkImageMat 进行计算。调用 extract 函数提取特征,并将结果存储在 feat_gpu 中。然后,使用 Vulkan 命令记录下载操作,并提交和等待命令执行。
  • 如果 d->opt.use_image_storage 为假,表示使用 VkMat 进行计算。同样地,调用 extract 函数提取特征,并将结果存储在 feat_gpu 中。然后,使用 Vulkan 命令记录下载操作,并提交和等待命令执行。
  1. 如果不支持 Vulkan 计算,或者 d->opt.use_vulkan_compute 为假,表示使用 CPU 进行计算。调用 d->net->d->forward_layer 函数执行网络的前向计算,计算结果存储在 d->blob_mats 中。
  2. 将提取得到的特征 d->blob_mats[blob_index] 赋值给输出参数 feat。
  3. 如果 d->opt.use_packing_layout 为真,并且 type 为 0,表示需要将特征的排列方式转换为非打包形式。调用 convert_packing 函数将特征转换为非打包形式,并将结果存储在 bottom_blob_unpacked 中,然后将其赋值给 feat。
  4. 根据配置,对特征进行数据类型转换。根据条件判断,可能会执行以下转换操作:
  • 如果支持 ARM 82 指令集(NCNN_ARM82 定义为真)并且 d->opt.use_fp16_storage 为真,并且 type 为 0,表示将特征从 float16 转换为 float32。
  • 如果支持 BF16 数据类型(NCNN_BF16 定义为真)并且 d->opt.use_bf16_storage 为真,并且 type 为 0,表示将特征从 bfloat16 转换为 float32。
  • 如果特征的元素位数为 8,并且 type 为 0,表示将特征从 int8 转换为 float32。
  1. 如果使用本地内存池分配器,并且 feat 的内存分配器与网络的本地blob 分配器不同,则需要将特征的内存从本地分配器复制到网络的本地 blob 分配器。
  2. 恢复之前保存的 KMP 块时间和 denormals 刷新设置。
  3. 返回 ret,即函数的返回值。

总体来说,这段代码的功能是从 ncnn 网络中提取指定索引的特征,并将其存储在给定的 Mat 对象中。根据配置和设备支持的特性,可能会进行数据类型转换和内存复制等操作。

为什么要重新设置KMP(OpenMP)块时间和 denormals 刷新?

重新设置 KMP(OpenMP)块时间和 denormals 刷新是为了在特征提取过程中优化计算性能和保证数值计算的准确性。

  1. KMP(OpenMP)块时间:KMP(OpenMP)是一种并行计算模型,可以将计算任务分配给多个线程并行执行。KMP 块时间指定了线程在空闲状态下等待新任务的时间。在特征提取过程中,通过设置适当的 KMP 块时间,可以在线程之间更好地分配计算资源,提高计算效率。
  2. denormals 刷新:denormals(非规格化数)是浮点数中的一种特殊情况,其数值非常接近零。在某些情况下,denormals 的出现可能会导致计算性能下降,因为对 denormals 的处理会引入额外的计算开销。为了提高计算性能,可以通过设置 denormals 刷新,将 denormals 强制为零,从而避免额外的计算开销。

重新设置 KMP(OpenMP)块时间和 denormals 刷新可以根据特征提取的需求,调整计算资源的分配和数值计算的准确性,以提高特征提取的效率和准确性。