This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320C6678:使用 MSMC 与 DDR3缓冲器的 OpenMP 吞吐量的性能基准测试。 为什么 OMP 并行运行比串行执行慢?

Guru**** 2020320 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/931479/tms320c6678-a-performance-benchmark-on-openmp-throughput-using-msmc-vs-ddr3-buffers-why-omp-parallel-run-is-slower-than-serial-execution

器件型号:TMS320C6678

大家好、

可能有些人已经注意到、我正在尝试(也很困难)使用  OpenMP 在 TMDSEVM6678LE 评估 DSP 模块上获得更好的速度性能(我知道 OMP 的内容现在正在休假。 我可能也会在本月晚些时候将此主题提请他们注意)。

之前、我启动了一个名为 Compiler/TMDSEVM6678的转换线程:OpenMP 堆管理 API 的用途是什么? 我在这里讨论了使用 OpenMP 与串行模式相比时运行缓慢的问题。  

而且,非常棒的建议是使用 MSMC RAM 作为 DDR3的一部分来获得更好的速度,因为所有线程都可以同时访问 MSMC,这实际上是非常有帮助的,这要归功于他的宝贵意见。  

根据建议、我开始创建一个简单的基准测试、以便在使用和不使用 OMP 的情况下比较和对比 MSMC 与 DDR3。 在下面的示例中,我使用 Memory_alloc (NULL,...)创建了两个大小相同的缓冲区,一个是从 MSMC 分配的,另一个是从 DDR3堆分配的。 。  

我对具有和不具有 OMP 的两个缓冲器的每个元素进行简单的数学运算。 下面是针对4个 OMP/NOOMP DDR3/MSMC 组合中每个组合所采用的时钟周期表:

1)显然、当 不使用 OMP 时、MSMC 在 char、float、double 和 long double 方面的工作速度高达5倍。 我只是想知道为什么只有这些数据类型?!!  

2) 2)为什么使用 OpenMP 仍然较慢、而 MSMC 应该同时由每个内核访问?

请告诉我我还可以做些什么,以便从 OpenMP 中获益。

如果您对编码有疑问或批评、我会非常高兴听到您的评论。  

我可能会在本月晚些时候将此主题提请本论坛注意。

此致、

基准 C 代码(白板.c)

#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 
#include 

typedef unsigned long long dt_uint64;
//typedef char buum_datatype;
//typedef short buum_datatype;
//tyedef int buum_datatype;
typedef float buff dataype;
//typedef double buff_datatype;
//typedef long double buff_datatype;


// MSMC
上的缓冲区#pragma DATA_SECTION (MSMC_bufSec、".MSMC_bufSec")
#pragma DATA_ALIGN (MSMC_buffer、128)
#define Bbuffer*(40 buffer1024) USC_datatype









;mSMC_buffer* main_chu_chu_chu_chu_chu_chu_bapn;// ma_ma_cher_cher* out_chor_chu_chu_buf
printf ("--=程序启动=-\n");

TSCH = 0;TSCL = 0;
dT_uint64 t_start、t_end;

ERROR_Block EB;
ERROR_INIT (&EB);
int blocksize = 256;

// NOOMP,MSMC 上的缓冲器
T_start =_itoll (TSCH、TSCL);
for (int j = 0;j < BUFLEN;j++){
MSMC_buff [j]= 1+(MSMC_buff [j]/2*3-50)/2*3-50;
}
T_end =_itoll (TSCH、TSCL);
printf ("NOOMP MSMC 缓冲区处理时间:%llu \n"、t_end - t_start);

T_start =_itoll (TSCH、TSCL);
// OMP,MSMC
#pragma omp 并行 num_threads (8)上的缓冲器
{
#pragma omp for
for (int j = 0;j < BUFLEN;j++){
// putchar ('M');putchar ('0'+ omp_get_thread_num ());
MSMC_buff [j]= 1+(MSMC_buff [j]/2*3-50)/2*3-50;
}
}
T_end =_itoll (TSCH、TSCL);
printf ("OMP MSMC 缓冲区处理时间:%llu \n"、t_end - t_start);

DDR_buff = Memory_alloc (NULL、BUFLEN* sizeof (buff 数据类型)、128、&EB);

if (!DDR_buff){
printf ("无法从堆中分配 DDR_buff \n");
退出(1);
}

//无 OMP,DDR 上的缓冲器
T_start =_itoll (TSCH、TSCL);
for (int j = 0;j < BUFLEN;j++){
DDR_buff [j]= 1+(DDR_buff [j]/2*3-50)/2*3-50;
}
T_end =_itoll (TSCH、TSCL);
printf ("NOOMP DDR 缓冲区处理时间:%llu \n"、t_end - t_start);

// OMP,DDR 上的缓冲器
T_start =_itoll (TSCH、TSCL);
#pragma omp parallel num_threads (8)
{
#pragma omp for
for (int j = 0;j < BUFLEN;j++){
DDR_buff [j]= 1+(DDR_buff [j]/2*3-50)/2*3-50;
}
}
T_end =_itoll (TSCH、TSCL);
printf ("OMP DDR 缓冲区处理时间:%llu \n"、t_end - t_start);



Memory_free (NULL、DDR_buff、BUFLEN*sizeof (buff 数据类型));

printf ("--=程序结束=-\n");
}

 

omp_config.cfg

/********* //*
段映射 */
********* /var
program = xdc.useModule('xdc.cfg.Program');

program.sectMap[".args"] = new Program.SectionSpec ();
program.sectMap[".bss"] = new Program.SectionSpec ();
program.sectMap[".cinit"] = new Program.SectionSpec ();
program.sectMap[".cio"] = new Program.SectionSpec ();
program.sectMap[".const"] = new Program.SectionSpec ();
program.sectMap[".data"] = new Program.SectionSpec ();
program.sectMap[".far"] = new Program.SectionSpec ();
program.sectMap[".fardata"] = new Program.SectionSpec ();
program.sectMap[".neardata"]= new Program.SectionSpec ();
program.sectMap[".rodata"] = new Program.SectionSpec ();
program.sectMap[".stack"] = new Program.SectionSpec ();
program.sectMap[".switch"] = new Program.SectionSpec ();
program.sectMap[".sysmem"] = new Program.SectionSpec ();
program.sectMap[".text"] = new Program.SectionSpec ();

//必须将这些段放在核心本地存储
器 program.sectMap[".args"].loadSegment 中 ="DDR3";
program.sectMap[".cio"].loadSegment ="L2SRAM";

//
在// OpenMP 中,以下数据段中的变量可能会被“共享”。 这些段必须放置在共享存储器中。
program.sectMap[".bss"].loadSegment ="DDR3";
program.sectMap[".cinit"].loadSegment ="DDR3";
program.sectMap[".const"].loadSegment ="DDR3";
program.sectMap[".data"].loadSegment ="DDR3";
program.sectMap[".far"].loadSegment ="DDR3";
program.sectMap[".fardata"].loadSegment ="DDR3";
program.sectMap[".neardata"].loadSegment ="DDR3";
program.sectMap[".rodata"].loadSegment ="DDR3";
program.sectMap[".sysmem"].loadSegment ="DDR3";

//内核共享的代码段-放置在共享存储器中以避免复制
program.sectMap[".switch"].loadSegment = program.platform.codeMemory;
program.sectMap[".text"].loadSegment ="MSMCSRAM";
PRINT (" program.platform.codeMemory ="、program.platform.codeMemory);

//调整默认堆栈的大小并将其放置在 L2SRAM
var deviceName = String (Program.cpu.deviceName);
// if (deviceName.search("DRA7XX")=-1){program.stack = 0x20000;}
// if (deviceName.search("DRA7XX")=-1){program.stack = 256*1024;} //在串行模式下工作
// if (deviceName.search("DRA7XX")=-1){program.stack = 330*1024;}
if (deviceName.search("DRA7XX")=-1){program.stack = 330*1024;}
// if (deviceName.search("DRA7XX")=-1){program.stack = 512*1024;}
否则 {program.stack = 0x8000;}
program.sectMap[".stack"].loadSegment ="L2SRAM";//在串行模式下工作256KB .stack
// program.sectMap[".stack"].loadSegment ="MSMCSRAM";//在 OpenMP 中不起作用

//由于没有参数传递给 main,因此将.args 大小设置为0
program.argSize = 0;


/******** /*
OpenMP 运行时配置*/********
/
use_OpenMP = true;
如果(use_OpenMP){
//在编译中包含 OMP 运行时
var ompSettings = xdc.useModule("ti.runtime.openmp.Settings");

//如果应用使用 BIOS 组件或依赖 BIOS 组件则设置为 true
ompSettings.usingRtsc = true;

如果(ompSettings.usingRtsc)
{
/*为 BIOS 配置 OpenMP
*- OpenMP* configureCores (masterCoreId、numberofCoresInRuntime)
* 配置主内核的 ID 和内核数
* 运行时可用。
*

VAR OpenMP = xdc.useModule('ti.runtime.ompbios.OpenMP');

//配置主内核的索引和可用内核的数量
//到运行时。 内核是连续的。
OpenMP*主 CoreIdx = 0;

//根据器件设置内核数
如果 (deviceName.search("DRA7XX")!=-1){OpenMP*= 2;}
否则,如果(deviceName.search("6670")!=-1){ OpenMP*= 4;}
否则,如果(deviceName.search("6657")!=-1){ OpenMP*= 2;}
否则,如果(deviceName.search("K2L")!=-1){ OpenMP*= 4;}
其他 { OpenMP*= 8;}

//拉入 Platform.XDC 中描述的内存范围以配置运行时
VAR DDR3 = Program.cpu.memoryMap["DDR3"];
VAR DDR3_NC = Program.cpu.memoryMap["DDR3_NC";
VAR MSMC = Program.cpu.memoryMap["MSMCSRAM"];
var msmcNcVirt= Program.cpu.memoryMap["OMP_MSMC_NC_virt"];
var msmcNcPhy = Program.cpu.memoryMap["OMP_MSMC_NC_PHY"];

//使用内存范围信息初始化运行时间
if (deviceName.search("DRA7XX")=-1){
OpenMP* msmcBase = MSMC.base
OpenMP* msmcSize = MSMC.len;

OpenMP* msmcNoCacheVirtualBase = msmcNcVirt.base;
OpenMP* msmcNoCacheVirtualSize = msmcNcVirt.len;

OpenMP*(msmcNoCachePhysicalBase)= msmcNcPhy.base;

//OpenMP*分配堆栈= true;
//OpenMP*分配标准版从 HeapSize = 4*330*1024;

}
其他
{
OpenMP*分配堆栈= true;
OpenMP*分配堆栈 FromHeapSize = 0x010000;

OpenMP* HASMsmc =错误;
OpenMP*版 NoCacheBase = DDR3_NC.base;
OpenMP*版。ddrNoCacheSize = DDR3_NC.len;
}

OpenMP*版 = DDR3.base;
OpenMP*文件大小 = DDR3.len;

//使用 HeapOMP 配置内存分配
// HeapOMP 句柄
//- BIOS 组件发出的内存分配请求(内核本地内存)
//-使用 IPC 模块启用共享内存分配
//从同一堆中分配内存的多个内核-由 malloc 使用
if (deviceName.search("DRA7XX")=-1){
打印("deviceName.search(\"DRA7XX\")=-1")
VAR HeapOMP = xdc.useModule('ti.runtime.ompbios.HeapOMP');

//必须为 IPC 初始化共享区域0
VAR sharedRegionId = 0;

//内核本地堆的大小
VAR localHeapSize = 0x8000;

//所有内核共享的堆的大小
// var sharedHeapSize = 0x08000000;
var sharedHeapSize =(512-32-22)*1024*1024;

//初始化共享区域并在 DDR3存储器区域中创建堆
VAR SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion');
SharedRegion.setEntryMeta (sharedRegionId、
{base:dr3.base、
Len:sharedHeapSize、
ownerProId:OpenMP*。masterCoreIdx、
高速缓冲启用:true、
createHeap:true、
IsValid:true、
名称:"DDR3_SR0"、
});

//配置和设置 HeapOMP
HeapOMP.configure (sharedRegionId、localHeapSize);

/*
var HeapTrack = xdc.useModule('ti.sysbios.heaps.HeapTrack');
var heapTrackParams = new HeapTrack.Params;
heapTrackParams.heap = HeapOMP;
var myHeapTracker = HeapTrack.create (heapTrackParams);
*}

其他
{
OpenMP.useIpcSharedHeap = false;
OpenMP*分配本地 HeapSize = 0x8000
OpenMP*分配共享 HeapSize = 0x00800000
}


VAR 启动= xdc.useModule('xdc.runtime.Startup');
startup.lastFxns.$add ('&_TI_omp_initialize_rtsc_mode');
}
否则
{
/*调整堆的大小。 必须将其放置在共享存储器中*
program.heap = sharedHeapSize;
}


//不使用 openmp
}否则{
var BIOS = xdc.useModule('ti.sysbios.BIOS');
BIOS.heapSize =(512-32-22)*1024*1024;
Program.sectMap["systemHeap"]= new Program.SectionSpec ();
Program.sectMap["systemHeap"].loadSegment="DDR3";
BIOS.heapSection ="systemHeapSect";



var BIOS = xdc.useModule('ti.sysbios.BIOS');
print ("BIOS.heapSize=

Program.sectMap[".msmc_bufSec"];"MSm100k.pru.csSize ="100k.cpupru.r";var BIOS ="systemHeapk.cpu.cpuat") 

生成日志




aK **为项目 arK_cpplab 构建配置调试****"c:\\ti\\ccs920\\ccs\\utils\\bin\\gmake.exe"所有调用:xDCtools "C:/ti/ccs920/xdctools_3_60_01_27_core/xs --xdcpath="C:/ti/openmp_dsp_c667x_2_06_03_00/packages;C:/ti/ipc_3_50_04_08/packages;C:/ti/openmp_dsp_c667x_2_06_03_00/packages/ti/runtime/openmp/platforms /Debug/configPkg;C:ti;C:/ti/bios_6_76_03_01/packages;" xdctools -config.p .c .c .t 包、因为/ti/pdk_c667x_2_0_16/packages ti.runtime.openmp.platforms.evm6678 -config.t /ti/ccs920/ccs/tools/compiler/ti-cgt-c6000_8.3.6
正在为软件包 configPkg 生成接口(因为 package/package.xdc.inc 比 package.XDC 旧)...
从 package/cfg/omp_config_pe66.cfg 配置 omp_config.xe66 ...
program.platform.codeMemory = MSMCSRAM
deviceName.search("DRA7XX")=-1
BIOS.heapSize = 4096
为器件配置 OpenMP 运行时:TMS320C6678
正在生成自定义 ti.SYSBIOS 库 makefile ...
链接库 ti.drv.qms:./lib/c66/ti.drv.qmss.ae66
链接库 ti.csl:./lib/c6678/c66/release/ti.csl.ae66
正在开始构建库源...
制作 C:/Users/Feng-laptop/workspace_v9_2_1/ark_cpplab/src/sysbios/sysbios.ae66 ...
已完成库构建。
cle66软件包/cfg/omp_config_pe66.c……
完工建筑:omp_config.cfg

"c:/ti/ccs920/ccs/tools/compiler/ti-cgt-c6000_8.3.6/bin/cl6x /Debug/configPkg/compiler.opt
/ti/openmp_dsp_c667x_2_06_03_00/packages/ti/runtime/openmp "-mv6600 -include_path="C:/ti/ccs920/ccs/tools/compiler/ti-cgt-c6000_8.3.6/include /ti/ccs920/ccs/tools/compiler/ti-cgt-c6000_8.3.6/bin/cl6x -include_path="C:/ti/openmp_dsp_c667x_2_06_03_00/packages/ti/runtime/openmp /ti/ccs920/ccs/tools/compiler/ti-cgt-c6000_8.3.6/include "-c99 -g -no_warnes--diag_warning=225 --include_wrap=off --display_error_number --cmd_file="_make_warnese-cn/msp_clocks=-tid_clocks=-tid_tid_clocks=-tid_dl_dlpine_tid_clocks=-tid_dlpet_dlpet_ctrab_dlpet_cep_ctrap_clocks=-dlpet_dl_dlpet_cep_clocks=-tid_dlpet_tid_tid_clocks -tid_iptid_ctrap_clocks=tid_clocks=tid_iptid_tid_iptid_iptid_clus-tid_clus_iptines=tid_dl_clus-tid_ctrap_clus-tag_ diag_warning=225 --diag_wrap=off --display_error_number -z -m"Debug/arK_cpplab.map"-i"C:/ti/ccs920/ccs/tools/compiler/ti-cgt-c6000_8.3.6/lib /ti/bios_6_76_02_02/packages/ti/targets/rts6000/lib/boot.ae66 /src/ipc/ipc.ae66 -i"C:/ti/ccs920/ccs/tools/compiler/ti-cgt-c6000_8.3.6/include /ti/bios_6_76_02_02/packages/ti/targets/rts6000/lib/ti.targets.rts6000.ae66 /src/sysbios/sysbios.ae66 -i"Debug/lib"--reread_libs --warn_wrap=off --display_error_number ---"libar_explor_line.xml_linkg-l_lineb/link/dlpintrab.dlpines"-/Debug/configPkg/linker.cmd -l.link_exctrab.dlpines"-/src/sysbios/sysbios.ae66 -l.dlpac/dlp_excab.dlpines"-/src/utils/utils.ae66 -dlp_exctrab.iptics"-l.iptex-l.ipticl.iptex-l.iptex-l.iptex_ex-l.ip

"./Debug/configPkg/linker.cmd、第118行:警告#10068-D:不匹配段
警告#10247-D:在不使用段规范的情况下创建输出段".tbss"
警告#10247-D:在不使用段规范
的情况下创建输出段".tdata"-=构建完成! =-****

构建完成****

 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、冯、

    OMP 专家目前不在办公室,将在他返回办公室后答复。

    雷克斯