请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
器件型号:C6000-CGT 工具/软件:TI C/C++编译器
您好!
我有一个函数、用于根据从多个 ADC 通道接收到的信号估算简单的协方差矩阵。 在-O3处优化代码时、启用软件流水线、并使我的协方差矩阵的输出偏离预期值。 有趣的是、偏差仅发生在 m 索引循环的第三次到第七次迭代上。
void calc_B (float* restrict B、int32_t n_chan、int32_t n_samples、float* samples) { int32_t* restrict 偏移1; int32_t* restrict 偏移2; int32_t idx; int64_t samples1; int64_t SAMPLES2; int64_t samples3; int64_t samples4; int32_t b_idx; int64_t ltmp; int32_t itmp; 浮点刻度; 浮点 ACC1; 浮点 ACC2; 浮点 ACC3; float acc4; int32_t n; int32_t m; //快于1/n_chirps scale =沉淀(n_samples); b_idx = 0; 对于(n = 0;n < n_CHAN;n++) { Offset1 =&input_samples[n_samples* n]; ACC1 = 0.0f); ACC2 = ACC1; ACC3 = ACC2; acc4 = ACC3; //第一个内环计算矩阵对角线元素 对于(idx = 0;idx < n_samples;idx += 8) { samples1 =_amem8 (偏移1 + idx); 功能 =_hill (samples1); lltmp=_mpy2ll (itmp、itmp); 功能 =_loll (samples1); lltmp =_dadd (lldmp、_mpy2ll (itmp、itmp)); ACC1 +=_hill (lltmp)+_loll (lltmp); SAMPLES2 =_amem8 (偏移1 + idx); 功能 =_hill (SAMPLES2); lltmp=_mpy2ll (itmp、itmp); 功能 =_loll (SAMPLES2); lltmp =_dadd (lldmp、_mpy2ll (itmp、itmp)); ACC2 +=_hill (lltmp)+_loll (lltmp); samples3 =_amem8 (偏移1 + idx); 功能 =_hill (samples3); lltmp=_mpy2ll (itmp、itmp); 功能 =_loll (samples3); lltmp =_dadd (lldmp、_mpy2ll (itmp、itmp)); ACC3 +=_hill (lltmp)+_loll (lltmp); samples4 =_amem8 (偏移1 + idx); 功能 =_hill (samples4); lltmp=_mpy2ll (itmp、itmp); 功能 =_loll (samples4); lltmp =_dadd (lldmp、_mpy2ll (itmp、itmp)); acc4 +=_hill (lltmp)+_loll (lltmp); } b[b_idx+]= Scale *(ACC1 + ACC2 + ACC3 + acc4); //对角线条目(右上角三角形) 对于(m = n + 1;m < n_chan;m++) { Offset2 =&input_samples[n_samples* m]; ACC1 = 0.0f; ACC2 = ACC2; 对于(idx = 0;idx < n_samples;idx += 4) { samples1 =_amem8 (偏移1 + idx); SAMPLES2 =_amem8 (偏移2 + idx); 功能 =_hill (SAMPLES2); lltmp =_mpy2ll (_hill (samples1)、itmp); 功能 =_loll (SAMPLES2); lltmp =_dadd (lldmp、_mpy2ll (_loll (samples1)、itmp); ACC1 +=_hill (lltmp)+_loll (lltmp); samples3 =_amem8 (偏移1 + idx + 2); samples4 =_amem8 (偏移2 + idx + 2); 功能 =_hill (samples4); lltmp =_mpy2ll (_hill (samples3)、itmp); 功能 =_loll (samples4); lltmp =_dadd (lldmp、_mpy2ll (_loll (samples3)、itmp); ACC2 +=_hill (lldmp)+_loll (lldmp); } b[rn_idx++])=比例*(ACC1 + ACC2); } }
我已经阅读了编译器指南中有关使用 volatile 关键字的建议(https://www.ti.com/lit/ug/sprui04c/sprui04c.pdf#page=65 第4.4.2节)。 使 ACC1和 ACC2变得易失性足以解决数字问题、但会导致性能下降(速度降低~25%)、这是无法容忍的。 读取生成的汇编代码看起来会使 ACC1/2变得易失性、从而破坏内部环路流水线。
为什么软件流水线循环只会干扰某些 m 索引循环值?
--柯蒂斯