You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言卷积函数传递3D数组的实现优化与嵌入式内存适配

2D卷积函数问题修复及嵌入式内存优化方案

1 编译错误修复

你遇到的field 'img' could not be resolved报错原因非常明确:函数形参中的N、M、P都是结构体指针类型,C语言中访问指针指向的结构体成员需要使用->运算符,而非.运算符。将卷积计算行修改为如下内容即可解决:

P->img[a][b][k] += N->img[ii][jj][p] * M->img[m][n][k];

另外现有代码的输出索引a/b计算逻辑存在越界风险,建议直接根据步长计算输出坐标:

int out_size = (size - ksize) / stride + 1;
// 循环内部对应输出位置改为
P->img[i/stride][j/stride][k] += ...

可完全避免索引计数错误问题。

2 嵌入式内存优化方案

针对嵌入式场景的内存限制,可从以下维度优化,保证每类3D数组仅占用一份可释放的内存空间:

2.1 替换固定尺寸结构体为动态张量结构

现有结构体写死了数组尺寸,实际使用时如果输入/输出尺寸小于定义值,会造成大量内存浪费。改用带柔性数组的通用张量结构,可实现内存按需分配:

// 通用3D张量结构体,内存连续分配
typedef struct {
    int w;
    int h;
    int c;
    float data[]; // 柔性数组成员,不占用结构体本身内存
} Tensor3D;

// 按需分配张量内存
Tensor3D* alloc_tensor(int w, int h, int c) {
    Tensor3D* t = malloc(sizeof(Tensor3D) + sizeof(float) * w * h * c);
    t->w = w;
    t->h = h;
    t->c = c;
    return t;
}

// 释放张量内存
void free_tensor(Tensor3D* t) {
    free(t);
}

使用该结构后,你调用时传入size=6的输入,就仅分配6x6x1的输入内存,不需要占用224x224x3的固定空间,可节省99%以上的冗余内存,使用完成后直接调用free_tensor释放即可,全程每类张量仅需分配一次。

2.2 无动态内存分配场景的静态优化

如果你的嵌入式平台不支持动态内存分配,可通过宏定义全局静态 buffer 实现固定内存占用:

// 按需调整宏定义的尺寸,全程仅分配一次
#define INPUT_W 224
#define INPUT_H 224
#define INPUT_C 3
#define KERNEL_SIZE 3
#define OUTPUT_W 112
#define OUTPUT_H 112
#define OUTPUT_C 32

static float input_buf[INPUT_H * INPUT_W * INPUT_C];
static float weight_buf[KERNEL_SIZE * KERNEL_SIZE * INPUT_C * OUTPUT_C];
static float output_buf[OUTPUT_H * OUTPUT_W * OUTPUT_C];

静态内存会在程序启动时一次性分配,不需要手动释放,也不会出现重复占用的问题。

2.3 循环逻辑优化减少内存访问开销

调整循环顺序、去掉不必要的边界判断,可减少缓存 miss 率,降低运行时的内存访问压力:

  • 将输入/输出的连续内存访问循环放在最内层,提升缓存命中率
  • 提前限制输入遍历的起止范围,去掉循环内部的边界判断分支:将i的遍历范围改为从ksize/2到size - ksize/2,不需要每次判断ii/jj是否越界

3 优化后卷积函数示例

void convolution(Tensor3D* input, Tensor3D* weight, Tensor3D* output, int stride) {
    int ksize = weight->h;
    int kcenter = ksize / 2;
    int out_idx = 0;
    for (int k = 0; k < output->c; k++) {
        for (int i = kcenter; i < input->h - kcenter; i += stride) {
            for (int j = kcenter; j < input->w - kcenter; j += stride) {
                float sum = 0.0f;
                for (int m = 0; m < ksize; m++) {
                    for (int n = 0; n < ksize; n++) {
                        int ii = i + m - kcenter;
                        int jj = j + n - kcenter;
                        for (int p = 0; p < input->c; p++) {
                            int input_idx = ii * input->w * input->c + jj * input->c + p;
                            int weight_idx = m * ksize * input->c * output->c + n * input->c * output->c + p * output->c + k;
                            sum += input->data[input_idx] * weight->data[weight_idx];
                        }
                    }
                }
                int out_h = i / stride;
                int out_w = j / stride;
                output->data[out_h * output->w * output->c + out_w * output->c + k] = sum;
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Ricardo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 05:48:03