跳转至

笔记

Big-Endian & Little-Endian

问题是否有意义

鸡蛋从哪头打破,怎么会有哪种更合适呢?对个人生活和社会发展又有什么意义呢?Swift写这段故事,其实是讽刺当时法国和英国的时政,认为真正重要的事情得不到关注、而在一些毫无意义的事情上争论不休。

各个阵营的选择

Motorola的PowerPC系列CPU采用Big-Endian方式存储数据,

而Intel的x86系列则采用Little-Endian方式存储数据。

JAVA虚拟机中多字节类型数据的存放顺序,也就是JAVA字节序是Big-Endian。

很多的ARM,DSP(Digital signal processor)都为小端模式。有些ARM处理器还可以随时在程序中(在ARM Cortex 系列使用REV、REV16、REVSH指令)进行大小端的切换。

忽略大小端的情况

得益于高级语言的发展,在现在的软件开发基本不需关心字节序(除非是socket编程),如Java这类跨平台移植的语言由虚拟机屏蔽了字节序问题。

对于大小端的处理也和编译器的实现有关,在C语言中,默认是小端(但在一些对于单片机的实现中却是基于大端,比如Keil 51C),Java是平台无关的,默认是大端。在网络上传输数据普遍采用的都是大端

大小尾端程序

华为鲲鹏AArch64 和 Intel x86 都是little-endian

需要进一步的研究学习

暂无

遇到的问题

暂无

开题缘由、总结、反思、吐槽~~

参考文献

LLVM-MCA: Install&RunTests

github

https://github.com/llvm/llvm-project/tree/main/llvm/tools/llvm-mca

Quick Start

安装

下载可执行文件上传服务器,解压

安装遇到的问题

  1. cannot find libtinfo.so.5
  2. sudo apt install libncurses5
  3. ln -s /usr/lib/libncursesw.so.6 /usr/lib/libtinfo.so.5 或者类似的 ln -s /usr/lib/libncurses.so.5 /usr/lib/libtinfo.so.5
  4. 在/snap/core下找到了,但是这是什么目录?是之前Ubuntu的包管理工具,但是已经不用了。

从源码安装

node5

由于之后要写代码的,还是从头安装更好。

cd llvm-project
mkdir build
cmake -S llvm -B build -G "Unix Makefiles" -DLLVM_ENABLE_PROJECTS="clang;llvm-mca" -DCMAKE_INSTALL_PREFIX="~/Install/llvm" -DCMAKE_BUILD_TYPE=Debug -DLLVM_ENABLE_ASSERTIONS=On
cd build
make -j32
make install

kunpeng

cmake -S llvm -B build -G "Unix Makefiles" -DLLVM_ENABLE_PROJECTS=all -DCMAKE_INSTALL_PREFIX="~/Install/llvm" -DCMAKE_BUILD_TYPE=Debug -DLLVM_ENABLE_ASSERTIONS=On
#change cmake or -DLLVM_ENABLE_PROJECTS="all"
error
g++: error: unrecognized command line option ‘-mllvm’
g++: error: unrecognized command line option ‘--tail-merge-threshold=0’
g++: error: unrecognized command line option ‘-combiner-global-alias-analysis’
change
cmake -S llvm -B build -G "Unix Makefiles" -DLLVM_ENABLE_PROJECTS="clang;llvm-mca" -DCMAKE_INSTALL_PREFIX="~/Install/llvm" -DLLVM_TARGETS_TO_BUILD=AArch64 -DCMAKE_BUILD_TYPE=Debug -DLLVM_ENABLE_ASSERTIONS=On

使用

clang foo.c -O2 -target x86_64-unknown-unknown -S -o - | llvm-mca -mcpu=btver2
由于不是X86,llc --version 查看到target是 aarch64-unknown-linux-gnu
clang /home/shaojiemike/Download/llvm-project-main/lldb/test/API/lang/c/forward/foo.c -O2 -target aarch64-unknown-linux-gnu -S -o -|llvm-mca -timeline -show-encoding -all-stats -all-views
生成汇编代码,并默认管道到llvm-mca,并开启所有输出。

可以看出是用TSV110Unit的port,默认cpu是tsv110

名词解释

ALU/BRU

算数逻辑单元 ALU 负责处理整数运算指令. 跳转处理单元BRU 负责处理跳转指令. BRU 可以与 ALU 合并, 复用 ALU 的逻辑来计算跳转指令的条件和跳转地址, 也可以作为一个单独的功能单元接入到流水线中.

MDU

乘除法单元 MDU (mult-divide unit)

需要进一步的研究学习

  1. llvm-mca微指令怎么实现的,怎么把汇编变成微指令
  2. 在view里加memory的实现
  3. 考虑了cache命中等影响 https://github.com/andreas-abel/uiCA uops
  4. 鲲鹏架构 https://bbs.huaweicloud.com/community/usersnew/id_1513665626477516

遇到的问题

  1. llvm-mca -mcpu=help竟然会卡住,不知道为什么
  2. 所以说是华为已经写了一个叫tsv110的,实现2个功能?

开题缘由、总结、反思、吐槽~~

参考文献

样例输出

Iterations:        100
Instructions:      200
Total Cycles:      70
Total uOps:        200

Dispatch Width:    4
uOps Per Cycle:    2.86
IPC:               2.86
Block RThroughput: 0.5


No resource or data dependency bottlenecks discovered.


Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[7]: Encoding Size

[1]    [2]    [3]    [4]    [5]    [6]    [7]    Encodings:                    Instructions:
 1      1     0.33                         4     20 00 80 52                   mov  w0, #1
 1      1     0.50                  U      4     c0 03 5f d6                   ret


Dynamic Dispatch Stall Cycles:
RAT     - Register unavailable:                      0
RCU     - Retire tokens unavailable:                 0
SCHEDQ  - Scheduler full:                            0
LQ      - Load queue full:                           0
SQ      - Store queue full:                          0
GROUP   - Static restrictions on the dispatch group: 0


Dispatch Logic - number of cycles where we saw N micro opcodes dispatched:
[# dispatched], [# cycles]
 0,              20  (28.6%)
 4,              50  (71.4%)


Schedulers - number of cycles where we saw N micro opcodes issued:
[# issued], [# cycles]
 0,          3  (4.3%)
 2,          1  (1.4%)
 3,          66  (94.3%)

Scheduler's queue usage:
No scheduler resources used.


Retire Control Unit - number of cycles where we saw N instructions retired:
[# retired], [# cycles]
 0,           3  (4.3%)
 2,           1  (1.4%)
 3,           66  (94.3%)

Total ROB Entries:                128
Max Used ROB Entries:             59  ( 46.1% )
Average Used ROB Entries per cy:  32  ( 25.0% )


Register File statistics:
Total number of mappings created:    100
Max number of mappings used:         29


Resources:
[0.0] - TSV110UnitAB
[0.1] - TSV110UnitAB
[1]   - TSV110UnitALU
[2]   - TSV110UnitFSU1
[3]   - TSV110UnitFSU2
[4.0] - TSV110UnitLdSt
[4.1] - TSV110UnitLdSt
[5]   - TSV110UnitMDU


Resource pressure per iteration:
[0.0]  [0.1]  [1]    [2]    [3]    [4.0]  [4.1]  [5]    
0.66   0.67   0.67    -      -      -      -      -     

Resource pressure by instruction:
[0.0]  [0.1]  [1]    [2]    [3]    [4.0]  [4.1]  [5]    Instructions:
0.33    -     0.67    -      -      -      -      -     mov w0, #1
0.33   0.67    -      -      -      -      -      -     ret


Timeline view:
Index     0123456789

[0,0]     DeER .   .   mov  w0, #1
[0,1]     DeER .   .   ret
[1,0]     DeER .   .   mov  w0, #1
[1,1]     D=eER.   .   ret
[2,0]     .DeER.   .   mov  w0, #1
[2,1]     .DeER.   .   ret
[3,0]     .D=eER   .   mov  w0, #1
[3,1]     .D=eER   .   ret
[4,0]     . DeER   .   mov  w0, #1
[4,1]     . D=eER  .   ret
[5,0]     . D=eER  .   mov  w0, #1
[5,1]     . D=eER  .   ret
[6,0]     .  D=eER .   mov  w0, #1
[6,1]     .  D=eER .   ret
[7,0]     .  D=eER .   mov  w0, #1
[7,1]     .  D==eER.   ret
[8,0]     .   D=eER.   mov  w0, #1
[8,1]     .   D=eER.   ret
[9,0]     .   D==eER   mov  w0, #1
[9,1]     .   D==eER   ret


Average Wait times (based on the timeline view):
[0]: Executions
[1]: Average time spent waiting in a scheduler's queue
[2]: Average time spent waiting in a scheduler's queue while ready
[3]: Average time elapsed from WB until retire stage

      [0]    [1]    [2]    [3]
0.     10    1.7    1.7    0.0       mov    w0, #1
1.     10    2.0    2.0    0.0       ret
       10    1.9    1.9    0.0       <total>

HPCthreeLaws

Amdahl's law

默认问题大小是固定的,导致最终可加速的倍率有上限 s是并行部分的加速比,p是可并行部分。

Gustafson's law

默认问题总时间固定,比如串行时间a,并行时间b,并行部分加速就是核数n, 并行部分就是\(F=\frac{a}{a+b}\)\(\(执行时间=a+b\)\) \(\(系统总执行时间=a+nb\)\) \(\(S=\frac{a+nb}{a+b}=F+n(1-F)\)\) 意义在于,当并行部分较多时,加速比与核数成正比。

Sun-Ni's Law

内存受限系统的加速比

这里的具体计算去看wiki

需要进一步的研究学习

暂无

遇到的问题

暂无

开题缘由、总结、反思、吐槽~~

参考文献

Static Code Analyzer on Kunpeng Overview

Static Code Analyzer Overview

What Is Static Analysis?

一种通过在程序运行之前自动检查源代码的调试方法。

What Is Static Code Analysis?

经常和source code analysis结合(貌似sourcetail的代码结构分析?

可以分析addresses weaknesses漏洞

IPC - Instructions per cycles

Throughput and Critical Path Analysis

好吧,都是机密,就不写了。

Chen advise

提高访存的方法 C-AMAT

目标

机密

需要进一步的研究学习

暂无

遇到的问题

暂无

开题缘由、总结、反思、吐槽~~

参考文献

IPCC Preliminary SLIC Optimization 6: Non-blocking MPI

非阻塞MPI

MPI_Send & MPI_receive

MPI_AllTogether()更慢,需要4s

手动向量化对齐

debug

 vx = _mm256_set_pd(x); #改成
 vx = _mm256_set_pd(x+3,x+2,x+1,x);

发现不对劲,打印更多输出。第一次循环肯定是对的因为和DBL_MAX比较。

需要进一步的研究学习

为什么明明有56GB的IB网,传输速度还是这么慢呢?写比较慢?

7*8=56 8条通道

遇到的问题

暂无

开题缘由、总结、反思、吐槽~~

参考文献

Hybrid Multithreaded/OpenMP + MPI parallel Programs

混合编程需要注意的问题

https://www.nhr.kit.edu/userdocs/horeka/batch_slurm_mpi_multithread/ 看这个

还有个ppt 16

google hydrid openmpi openmp

intelmpi 编译

这里值得要注意的是,似乎直接用mpif90/mpicxx编译的库会报错,所以需要用

icc -openmp hello.cpp -o hello -DMPICH_IGNORE_CXX_SEEK -L/Path/to/mpi/lib/ -lmpi_mt -lmpiic -I/path/to/mpi/include 其中-DMPICH_IGNORE_CXX_SEEK为防止MPI2协议中一个重复定义问题所使用的选项,为了保证线程安全,必须使用mpi_mt库

对于intel的mpirun,必须在mpirun后加上-env I_MPI_PIN_DOMAIN omp使得每个mpi进程会启动openmp线程。

通过export OMP_NUM_THREADS来控制每个MPI产生多少线程。

OpenMPI 如何实现mult-thread(OpenMP)2

检查编译安装支持mult-thread

shell$ ompi_info | grep "Thread support"
          Thread support: posix (MPI_THREAD_MULTIPLE: yes, OPAL support: yes, OMPI progress: no, Event lib: yes)
shell$
"MPI_THREAD_MULTIPLE: yes"说明是支持的。

在C程序里支持mult-thread

#include <mpi.h>
int MPI_Init_thread(int *argc, char ***argv,
    int required, int *provided)

argc
        C/C++ only: Pointer to the number of arguments.
argv
        C/C++ only: Argument vector.
required
        Desired level of thread support (integer).
provided
        Available level of thread support (integer).
required 可选值 分别是0,1,2,3
MPI_THREAD_SINGLE
        Only one thread will execute.
MPI_THREAD_FUNNELED
        If the process is multithreaded, only the thread that called MPI_Init_thread will make MPI calls.
MPI_THREAD_SERIALIZED
        If the process is multithreaded, only one thread will make MPI library calls at one time.
MPI_THREAD_MULTIPLE
        If the process is multithreaded, multiple threads may call MPI at once with no restrictions.
MPI_Init_thread调用MPI_thread_SINGLE等同于调用MPI_Init。

注意

3.1.6的多线程支持还在初级阶段。开销很高(虽然我不知道为什么)

需要进一步的研究学习

学习MapReduce或者Hadoop? pthread vs openmp?

遇到的问题

暂无

开题缘由、总结、反思、吐槽~~

参考文献

https://blog.csdn.net/Morizen/article/details/113863591

[2] OpenMPI-multThread

IPCC Preliminary SLIC Optimization 5: MPI + OpenMP

AMD

技术路线 描述 总时间 加速比 备注
Baseline 串行程序 161.7s s 1
more3omp 前面都是可以证明的有效优化 omp_num=32 14.08s
more3omp 前面都是可以证明的有效优化 omp_num=64 11.4s
deletevector 把sz大小的3个vector,移到全局变量,但是需要提前知道sz大小/声明一个特别大的 10.64s 可以看出写成全局变量也不会影响访问时间
enforce_Lscan IPCC opt 4 8.49s 19
enforce_Lscan_MPI_intel intel icpc 3.8s 42.36
Baseline2-max ppm 1.2GB ppm 10*1024*40*1024 928s
enforce_Lscan Baseline2 43.79s 21.2
enforce_Lscan_MPI_intel intel icpc + 双节点两个时间 + MPI(DoRGBtoLABConversion) 18.8s / 20s 46.4
enforce_Lscan_intel intel icpc + 单节点 15.8s 58.74 MPI(DoRGBtoLABConversion)负优化了2s
manualSIMD 13.9s
stream 13.6s
vec2mallocOMP 11.0s
mmap 10.6s
+ -O3 enforce_Lscan_intel 16.2s
+ -xHost 结果不对 17.8s
-Ofast 16.9s
-ipo 15.9s
-O3 -ipo 16.8s
-O3 -march=core-avx2 -fma -ftz -fomit-frame-pointer 16.0s
g++ suggested options -O3 -march-znver1 -mtune=znver1 -fma -mavx2 -m3dnow -fomit-frame-pointer 18.1s
g++ suggested options2 -O3 -march-znver2 -mtune=znver2 -fma -mavx2 -m3dnow -fomit-frame-pointer 19.79s
g++ -Ofast 16.9s
aocc -Ofast 16.3s
aocc suggested options 16.2s

MPI编程

由于是打算两节点两进程MPI,虽然没有OpenMP的共享内存,但是也希望通信能少一点。

PerformSuperpixelSegmentation_VariableSandM

下面关于同步区域的想法是错误的: 因为中心点移动会十分不确定,所以全部同步是最好的。

  1. 第一部分core的思路
  2. 上面numk个中心点直接一分为2,需要同步的是中间相连的\(\(width*(3S)\)\)个中心点(由于PerturbSeeds扰动,而且offset比较大,应该是中间相邻的2排,大约3S的高度的区域,上下1.5S高度)。
  3. distlab需要后面覆盖前面的(当然是计算了的区域)。klabels是取distvec更小对应的那个,应该要写个自定义归约。
  4. numk个中心点有奇数行和偶数行,经过思考后是一样的。
  5. 第二部分各中心maxlab的思路(从sz里提取numk个中心的数据)
  6. sz直接一分为2,最小同步的话,就是中间相邻中心点maxlab要max归约。
  7. 第三部分计算sz里的numk个中心点的质心和
  8. 同理,sz直接一分为2,vector相加归约同步

DoRGBtoLABConversion 0.61s

用MPI_Send写,但是一开始没注意是阻塞的,但是为什么这么慢呢?

对比之前的enforce_Lscan 8.49s
  1. DoRGBtoLABConversion 0.56s
  2. PerformSuperpixelSegmentation_VariableSandM 5.52s
  3. core 0.53s
  4. maxlab 0.02s
  5. sigma 0.03s
  6. DetectLabEdges 0.31s
  7. EnforceLabelConnectivity 1.19s
  8. PerformSuperpixelSegmentation_VariableSandM 0.88s

慢了10~20倍猜测: 1. printf的原因? no 不打印也一样 2. omp_num的值不对? maybe no 3. 不在两个节点上? no 4. g++ mpicxx? no 5. 没有用IB ? 貌似也不是 6. openmpi不支持openmp ? 探究方向

好像是openmp没正常运行omp_num的值为 1,32,64时间都一样。感觉是混合编程的编译问题, 而且好像是假Openmp并行,哪里有锁的样子。突然想起来,Quest的混合变成cmake需要打开multthread类似的支持,但是这里并没用。

好像也不是mpi_init_thread的问题

尝试intelmpi

果然有奇效。(结果是对的,后面我没截图了)。看到这里,可能你会觉得这个问题是OpenMPI有地方不支持openmp。但是后面有神奇的事情,如果NODELIST是fa,而不是fb就不能跑,会直接卡住。😰

首先没找到官方手册说明不同,然后研究一下这两个分区的不同。好吧从IB,cpu,内存都没区别。

限制nodelist再跑一遍。

加上打印时间,用fb分区

这个问题又没有了,但是fa分区由于经常跑可能会热一些。

最大的ppm例子

由于时间已经进5s了。所以我们需要更大的例子,再讨论2节点的开销收益,之前的例子是256034000。 这里生成了1024040960的ppm.再大ppm程序的数组都申请不到栈空间了,需要重新数据结构。

重跑当前最快的enforce_Lscan

icpc + enforce_Lscan_MPI(DoRGBtoLABConversion) icpc + enforce_Lscan g++ suggested options icpc + manualSIMD + lessLscan icpc + manualSIMD + LscanSimple icpc + manualSIMD + LscanSimple + stream icpc + manualSIMD + LscanSimple + stream + mallocOMPinit icpc + manualSIMD + LscanSimple + stream + mallocOMPinit + mmap icpc + manualSIMD + LscanSimple + stream + mallocOMPinit + mmap + unrollLoop

放弃的原因

https://www.bilibili.com/video/BV1a44y1q782 58mins-58min50s

需要进一步的研究学习

暂无

遇到的问题

  1. 混合编程写的有问题,双节点不快反慢。怎么写呢?
  2. 那段串行代码真的不能并行吗?
  3. 向量化为什么没有提升呢,是要循环展开吗?

姜师兄建议

  1. MPI非阻塞通信 gather reduce
  2. 手动向量化

开题缘由、总结、反思、吐槽~~

参考文献