各位大神好,
我最近想做使用DSPC6678来实现一个算法的实时性,用到了CCS8.3 win10 c6678的板子,由于对DSP性能还不熟悉暂时只用一个核去做了处理。
但是发现在vs中同样的.c程序只用25s,而在DSP中用TSCL检测出来(release下)需要3000s,大大超出了我的遇期(目的是想要减少时间啊)。
代码没有改动,只是代码中申请使用很多动态数组,一维,二维,三维都有用到,算法中也有很多子函数,用到了很多循环。用了系统自带的C6678的.cmd文件。想向大家请教一下是哪里还需要改设置吗,为什么时间会差距这么大? 以下是我的.cmd文件和主函数的代码。十分感谢~~
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include "math.h" #include "time.h" #include "c6x.h" // 读取到的图像,存储到DDR3中 #pragma DATA_SECTION(num,".imageData") #pragma DATA_ALIGN(num, 256)// 256字节对齐 double num[3]; #define inner_win_size 11 #define out_win_size 33 void readimagedata(double *fp, int H, int W, int Dim, double ***array); double ***padarray(double ***h, int H, int W, int Dim); void RXD_function(double ***h, double *mean, double **inv, double **RXD, int Dim, int i, int j); double **sequential_inv(double **cov, double **aug, int num, int row, int col, char a); void row_cycle(double ***array, double **aug_plus, double **aug_subtract, double **cov, double *mean, double ***inv_cov_1, double **mean_1, int Dim, int W, double ***h, double **RXD); void col_cycle(double ***array, double **aug_plus, double **aug_subtract, double **cov, double *mean, double ***inv_cov_1, double **mean_1, int H, int W, int Dim, double ***h, double **RXD); void cov_inv(double **m, int H, int Dim, double *mean, double lambda, double **cov); void Firstinv(double ***array, int Dim, double **temp, double *mean, double **cov); double*** Malloc3DActiveArray(int x, int y, int z); void Free3DActiveArray(double *** pArr, int x, int y); double** Malloc2DActiveArray(int x, int y); void Free2DActiveArray(double ** pArr, int x); int main() {FILE *fid;fid = fopen("E:\\ccs_workspace\\fast_rx_s_2\\test_double.dat", "rb");if (fid == NULL){printf("error on open file!\n");}printf("test console!\n");double num[3];fread(&num, sizeof(double), 3, fid);int H = num[0];int W = num[1];int Dim = num[2];double *pos = (double*)malloc(sizeof(double)*H*W*Dim);fread(pos, sizeof(double), H*W*Dim, fid);fclose(fid);printf("pos is ok!\n");double *** h = NULL;h = Malloc3DActiveArray(H, W, Dim);readimagedata(pos, H, W, Dim, h);fclose(fid);free(pos);unsigned long long t1,t2;TSCH=0;TSCL=0;t1=_itoll(TSCH,TSCL);//t1=TSCL;printf("h is ok!\n");double *** array = NULL;array = Malloc3DActiveArray(H + out_win_size-1, W + out_win_size-1, Dim);array = padarray(h, H + out_win_size-1, W + out_win_size-1, Dim);double **a = NULL, **cov = NULL;double *mean = (double *)malloc(Dim * sizeof(double));a = Malloc2DActiveArray(8 * inner_win_size*inner_win_size, Dim);cov = Malloc2DActiveArray(Dim, Dim);Firstinv(array, Dim, a, mean, cov);double ***inv_cov_1 = NULL;inv_cov_1 = Malloc3DActiveArray(Dim, Dim, W);double **mean_1 = NULL;mean_1 = Malloc2DActiveArray(Dim, W);int i, j;for (i = 0; i < Dim; i++){for (j = 0; j < Dim; j++){inv_cov_1[i][j][0] = cov[i][j];}mean_1[i][0] = mean[i];}double **RXD = NULL;RXD = Malloc2DActiveArray(H, W);RXD_function(h, mean, cov, RXD, Dim, 0, 0);printf("RXD_1 is ok!\n");double **aug_plus = NULL;aug_plus = Malloc2DActiveArray(4 * inner_win_size + 1, Dim);double **aug_subtract = NULL;aug_subtract = Malloc2DActiveArray(4 * inner_win_size + 1, Dim);row_cycle(array, aug_plus, aug_subtract, cov, mean, inv_cov_1, mean_1, Dim, W, h, RXD);printf("row_cycle is ok!\n");col_cycle(array, aug_plus, aug_subtract, cov, mean, inv_cov_1, mean_1, H, W, Dim, h, RXD);t2=_itoll(TSCH,TSCL);//t2=TSCL;printf("cycle = %lld \n",t2-t1);printf("all complete!");FILE *fid1;fid1 = fopen("RXD_double_r.dat", "wb");if (fid1 == NULL){printf("error on open wfile!\n");}double *f = (double*)malloc(sizeof(double)*Dim*Dim);for (i = 0; i < H; i++){for (j = 0; j < W; j++){f[i*H + j] = RXD[i][j];}}fwrite(f, sizeof(double), H*W, fid1);fclose(fid1);Free3DActiveArray(h,H,W);Free3DActiveArray(array, H + out_win_size - 1, W + out_win_size - 1);Free2DActiveArray(a,8*inner_win_size*inner_win_size);Free2DActiveArray(cov,Dim);Free3DActiveArray(inv_cov_1,Dim,Dim);Free2DActiveArray(mean_1,Dim);Free2DActiveArray(RXD,H);Free2DActiveArray(aug_plus, 4 * inner_win_size + 1);Free2DActiveArray(aug_subtract, 4 * inner_win_size + 1);return 0; }
.cmd文件
MEMORY {LOCAL_L2_SRAM: o = 0x00800000 l = 0x00080000/* 512kB LOCAL L2/SRAM */LOCAL_L1P_SRAM: o = 0x00E00000 l = 0x00008000/* 32kB LOCAL L1P/SRAM */LOCAL_L1D_SRAM: o = 0x00F00000 l = 0x00008000/* 32kB LOCAL L1D/SRAM */SHRAM:o = 0x0C000000 l = 0x00400000/* 4MB Multicore shared Memmory */EMIF16_CS2:o = 0x70000000 l = 0x04000000/* 64MB EMIF16 CS2 Data Memory */EMIF16_CS3:o = 0x74000000 l = 0x04000000/* 64MB EMIF16 CS3 Data Memory */EMIF16_CS4:o = 0x78000000 l = 0x04000000/* 64MB EMIF16 CS4 Data Memory */EMIF16_CS5:o = 0x7C000000 l = 0x04000000/* 64MB EMIF16 CS5 Data Memory */DDR3:o = 0x80000000 l = 0x80000000/* 2GB CE0 and CE1 external DDR3 SDRAM */ } SECTIONS {.text> SHRAM.stack> DDR3.bss> SHRAM.cio> SHRAM.const> SHRAM.data> SHRAM.switch> SHRAM.sysmem> DDR3.far> SHRAM.args> SHRAM.ppinfo> SHRAM.ppdata> SHRAM/* COFF sections */.pinit> SHRAM.cinit> SHRAM/* EABI sections */.binit> SHRAM.init_array> SHRAM.neardata> SHRAM.fardata> SHRAM.rodata> SHRAM.c6xabi.exidx > SHRAM.c6xabi.extab > SHRAM.imagedata> DDR3 }
Ryan BL:
你们需要个DSP优化,无论从实现上的优化还是工程的优化。
最简单来说,在编译的时候加上-o[0-3]优化,会有比较大的速率提升;
如果你们在成都,那么我刚好打算换工作了,可以联系哟:)
Shine:
回复 Ryan BL:
先用优化选项-O3优化一下代码。
user5179571:
回复 Shine:
您好,我在Properties->Bulid->C6000 Complier->Optimization 中将Optimization level的选项改成了-O3,不知道这样修改是不是对的。但是程序在读取数据时出错,读取的num[0],num[1],num[2]是正确的,但是变为int型的H,W,Dim就会出错,加上强制转换也不行。修改了优化选项,只有-O0不会出错,但速度几乎没有提升。(看到H是正确的,W,Dim的地址显示在寄存器)请问这个问题应该怎么解决呢?急求,谢谢。
Tao_LL:
1.将cmd中system从DDR改为SHRAM
2.用内敛指令
3.预编译
Ryan BL:
回复 Tao_LL:
能放SHRAM或Local—L2的尽量往里面放,高速内存很重要;
少用malloc,建议直接固定专用内存;
循环优化是关键,三维这种要尽可能杜绝,尽量使用一维;
计时中间调用的算法,里面尽可能少打印,确实需要可以使用bios的system.min的打印到ROV,不要直接打印到控制台;
至于你说的出错,这个比较麻烦点,经常是编译器没太理解到你的意图或数据依赖关系给过分优化了,尝试换种写法试试;
user5179571:
回复 Ryan BL:
十分感谢。我尝试了用一维数据去做,但是貌似还是在malloc遇到了问题。因为我需要处理不同大小的数据集,所以感觉只能用malloc去分配内存,因为我预先不知道大小是多少。但是现在,在第一部为pos分配内存时就特别慢(起初我还以为是fread的原因,我还特意换成了二进制的数据文件),所以我现在想请教malloc该如何使用,申请过程都要半小时以上是什么 原因呢?我现在跑的数据是64*64*169的,其他数据更大。之前把system放到DDR中也是因为申请数组过大。现在将-heap和-stack改成0x300000,-system放到了SHRAM中。以上情况是基于此出现的,之前遇到的问题换了写法解决了。谢谢~
user5179571:
回复 Tao_LL:
您好,谢谢您的回复。我将system放到DDR中是因为要动态分配的数据很大,SHRAM中怕放不下。
您说的内敛指令和预编译(#pragma?)可以详细一点说怎么用吗,或者您有没有合适的学习资料可以推荐我使用?十分感谢~~
现在malloc貌似是最耗时的步骤,将申请64*64*169的内存需要耗费半小时,将stack和heap改为0x300000以后(之前是0x10000000)fread读取不进去了。
Ryan BL:
回复 user5179571:
按照你要用的最大,定义个放在MSMC或LL2的内存,这个仅是普遍的通用情况;
实际考虑数据应该是一部分一部分处理的,一般是把即将要处理的数据ping/pong倒换,处理完一块用EDMA做背景传输,而后处理另一块,在处理结果搬移完后使用EDMA级联个下一次要处理的数据。这个属于整个数据流上的优化;
然后就是,file操作是很费时的,因为jtag速率受限,而且那块会占用大量的dsp时间,建议直接把这个文件使用Memory Browser导入内存再处理,因为你最终处理数据,这个数据也应该是SRIO或网络或PCIE通道获取的。
Ryan BL:
回复 user5179571:
应该是笔误,是“内联”,导入“c6x.h" 头文件,你使用的运算尽可能优化成使用里面定义的接口;
看不懂或不明白是什么意思的话,这里有: