@plutarch 这个确实是,官网上应该有一包示例代码
swmore 发布的帖子
-
RE: 请问dma_barrier如何使用呢?
@sam 需要注意的一件事情是,
dma_barrier
只能使后续的DMA操作无法发出, 但是其他指令会继续执行.
如果想要不执行后面的命令可以试试这样搞:#define pe_init() volatile int _reply = 0, _count = 0; #define pe_get(src, dst, size) {athread_get(PE_MODE, src, dst, size, &_reply, 0, 0, 0); _count ++}; #define pe_put(src, dst, size) {athread_put(PE_MODE, src, dst, size, &_reply, 0, 0, 0); _count ++}; #define pe_syn() while (_reply != _count);
然后发出
athread_get/athread_put
请求时自动更新count, 使得编程容易一点.void test(){ pe_init(); //一堆pe_get... pe_syn(); }
-
RE: 大规模并行中的从核exception定位方案
可以用这种比较简单点的方法获取到从核的PC以及SDLB和DMA Exception的报错现场.
#include <athread.h> #include <signal.h> long cgid; #define IO_GET(addr) (*(long*)(addr)) #define CPE_BASE_ADDR(cpe_id) (0x8003000000L | cgid << 36L | cpe_id << 16L) #define CPE_PC_ADDR 0x2000 inline long get_cpe_pc(int cpe_id){ //return *(long*)(0x8003002000L | cgid << 36L | cpe_id << 16L); //return *(long*) CPE_BASE_ADDR(cpe_id) | CPE_PC_ADDR; return IO_GET(CPE_BASE_ADDR(cpe_id) | CPE_PC_ADDR); } #define TC_BASE_ADDR (0x8004000000L | cgid << 36L) #define TC_SDLB_ERR_PEVEC 0x308000L #define TC_SDLB_ERR_SPOT 0x308080L char *SDLB_REQ_TYPE_STR[] = {"read", "write", "faa", "updt+", "updt-"}; char *SDLB_REQ_SRC_STR[] = {"cpe", "ibox", "dma"}; char *BOOL_STR[] = {"no", "yes"}; inline void decode_sdlb_err(){ puts("==============DECODE OF SDLB ERROR SPOT=============="); long spot = IO_GET(TC_BASE_ADDR | TC_SDLB_ERR_SPOT); printf("TC_SDLB_ERR_SPOT: %lx\n", spot); long reqtype = spot & 7; printf("REQ_TYPE: %s\n", SDLB_REQ_TYPE_STR[reqtype]); long src_pe = spot >> 40 & 63; printf("SRC_PE: %d\n", src_pe); long grain = spot >> 46 & 2; printf("GRAIN: %d\n", 1 << grain); long src_id = spot >> 59 & 3; printf("SRC_TYPE: %s\n", SDLB_REQ_SRC_STR[src_id - 1]); long oor = (spot >> 61) & 1; printf("OUT_OF_RANGE: %s\n", BOOL_STR[oor]); long oop = (spot >> 62) & 1; printf("OUT_OF_PERM: %s\n", BOOL_STR[oop]); } #define GC_BASE_ADDR (0x8005000000L | cgid << 36L) #define GC_DMACHK_TYPE 0x200700L char *DMA_ERR_STR[] = { "LDM unaligned", "MEM unaligned", "size unaligned", "bsize unaligned", "stride unaligned", "GET_P/PUT_P occur", "size non positive", "", "invalid OP", "invalid MODE", "invalid OP+MODE", "reply overflow/unaligned", "LDM overflow", "bcast vec=0", "not connected" }; void decode_dma_chk(){ puts("================DECODE OF DMACHK_TYPE================"); long chk = IO_GET(GC_BASE_ADDR | GC_DMACHK_TYPE); long type; puts("CHK_TYPE:"); for (type = 0; type <= 14; type ++) if ((1 << type) & chk){ printf("\t%s\n", DMA_ERR_STR[type]); } long src_pe = chk >> 16 & 63; printf("SRC_PE: %d\n", src_pe); } void expt_decoder(int sig){ printf("writing cpe PCs on signal %d\n", sig); int i, j; for (i = 0; i < 8; i ++) { for (j = 0; j < 8; j ++) printf("%3d: %12llx ", i * 8 + j, get_cpe_pc(i * 8 + j)); puts(""); } decode_sdlb_err(); decode_dma_chk(); } extern void slave_gid(long *); void sig_init(int rank){ if (!athread_idle()) athread_init(); long cid; athread_spawn(gid, &cid); athread_join(); cgid = cid; }
上面这段代码里面expt_decoder是解析从核错误并打印到屏幕的函数, sig_init是初始化核组号的函数. 里面调用了一个叫gid的从核函数用于获取核组号, 实现如下:
#include <slave.h> #include <simd.h> void gid(long *_id){ long cid; asm ("rcsr %0, 0\n\t": "=r"(cid)); if (!_MYID){ *_id = cid >> 6; } } #endif
可以配合wrap expt_handler使用目测效果拔群.
函数原型我的印象是__expt_handler(void *a, void *b)
能够兼容, 可以这么写:void __wrap___expt_handler(void *a, void *b){ //大神的解析栈代码. expt_decoder(0); __real___expt_handler(a, b); }
另外, wrap只需要在最后链接的时候加.
-
RE: 请问如何神威如何编译大文件?
使用了太多的代码段内存?
比如int main(){ int a_very_large_array[1024 * 1024 * 1024 * 2]; }
之类的?
这样不好.
太大的东西还是应该动态分配.