NCCL Tree

NCCL Tree源码

https://github.com/NVIDIA/nccl/blob/master/src/misc/trees.c
https://github.com/NVIDIA/nccl/pull/172

为了让代码运行起来,进行了小改

#include <iostream>
using namespace std;

int GetBtree(int nranks, int rank, int* u, int* d0, int* d1);
int GetDtree(int nranks, int rank, int* s0, int* d0_0, int* d0_1, int* s1, int* d1_0, int* d1_1);

main()
{
    int nranks=12;
    int i=0, u=0, d0=0, d1=0, du=0, dd0=0, dd1=0;
    for ( i=0; i<nranks; i++ ) {
    GetDtree (nranks, i, &u, &d0, &d1, &du, &dd0, &dd1);
    cout << "i=" << i << ";\tu=" << u << ",\td0=" << d0 << ",\td1=" << d1 << endl;
    cout << "\tdu=" << du << ",\tdd0=" << dd0 << ",\tdd1=" << dd1 << endl;
    }
}

//得到单向tree
int GetBtree(int nranks, int rank, int* u, int* d0, int* d1) {
  int up, down0, down1;
  int bit;
//和IP掩码类似,从低位往高位,第一个不为0的位,标志了这个节点以下的子树边界
  for (bit=1; bit<nranks; bit<<=1) {
    if (bit & rank) break;
  }

  if (rank == 0) {
    *u = -1;
    *d0 = nranks > 1 ? bit >> 1 : -1;
    *d1 = -1;
    return 0;
  }

  up = (rank ^ bit) | (bit << 1);
  if (up >= nranks) up = (rank ^ bit);
  *u = up;

  int lowbit = bit >> 1;

  down0 = lowbit == 0 ? -1 : rank-lowbit;

  down1 = lowbit == 0 ? -1 : rank+lowbit;

  while (down1 >= nranks) {
    down1 = lowbit == 0 ? -1 : rank+lowbit;
    lowbit >>= 1;
  }
  *d0 = down0; *d1 = down1;

  return 0;
}

int GetDtree(int nranks, int rank, int* s0, int* d0_0, int* d0_1, int* s1, int* d1_0, int* d1_1) {

  GetBtree(nranks, rank, s0, d0_0, d0_1);

  if (nranks % 2 == 0) {

    int shiftrank = (rank-1+nranks) % nranks;
    int u, d0, d1;
    GetBtree(nranks, shiftrank, &u, &d0, &d1);
    *s1 = u == -1 ? -1 : (u+1) % nranks;
    *d1_0 = d0 == -1 ? -1 : (d0+1) % nranks;
    *d1_1 = d1 == -1 ? -1 : (d1+1) % nranks;
  } else {
    int shiftrank=nranks-rank;
    int u, d0, d1;
    GetBtree(nranks, shiftrank, &u, &d0, &d1);
    *s1 = u == -1 ? -1 : nranks-u;
    *d1_0 = d0 == -1 ? -1 : nranks-d0;
    *d1_1 = d1 == -1 ? -1 : nranks-d1;
  }
  return 0;
}

NCCL-tree生成的ranking方案

代码需要修改一下才能实现注释中提到的ranking方案

奇数节点Ranking

对于奇数个rank,比如下图的13,NV建议对第二个tree采用mirror ranking,也就是结构上镜像

文档中原图
 *                 8---------0---------5
 *          ______/ \______      _____/ \______
 *         4               12   1              9
 *       /   \            /      \           /   \
 *     2       6       10          3       7      10
 *    / \     / \     /  \        / \     / \    /  \
 *   1   3   5   7   9   11      2   4   6   8  11  12
 *

这里文档的右下角写错了,因为如果按照这个路子画,程序跑出来的树应该是

修正右下角
*                 8---------0---------5
 *          ______/ \______      _____/ \______
 *         4               12   1              9
 *       /   \            /      \           /   \
 *     2       6       10          3       7      11
 *    / \     / \     /  \        / \     / \    /  \
 *   1   3   5   7   9   11      2   4   6   8  12  10                                 

如果不按照NV的做法,直接shift ranking,那么就是下图所示的结构,看上去也不错

在奇数节点中应用shift ranking
*                 8---------0-----------------9
 *          ______/ \______            ______/ \______    
 *         4               12         5               1  
 *       /   \            /         /   \            /    
 *     2       6       10         3       7       11      
 *    / \     / \     /  \       / \     / \     /  \     
 *   1   3   5   7   9   11     2   4   6   8   10   12    

偶数节点ranking

对于偶数个rank,比如下图的12,NV建议采用shift ranking

文档中原图
 * or shift it by one rank (if nranks is even)
 *
 *                 8---------0--------------9
 *          ______/ \                ______/ \
 *         4         \              5         \
 *       /   \        \           /   \        \
 *     2       6       10       3       7       11
 *    / \     / \     /  \     / \     / \     /  \
 *   1   3   5   7   9   11   2   4   6   8   10   1
 */

这里文档又写错了,真正运行出来的结果应该是1变成了新root

修正根节点
 *                 8---------0--1-----------9
 *          ______/ \                ______/ \
 *         4         \              5         \
 *       /   \        \           /   \        \
 *     2       6       10       3       7       11
 *    / \     / \     /  \     / \     / \     /  \
 *   1   3   5   7   9   11   2   4   6   8   10   0

我试试这个结构能不能做mirror ranking
结果发现leaf节点还都是奇数编号,这就是为啥偶数ranks时候不能mirror的原因

在偶数节点中应用mirror ranking
 *                 8---------0--------4
 *          ______/ \                / \______
 *         4         \              /         8
 *       /   \        \            /        /  \
 *     2       6       10         2        6     10
 *    / \     / \     /  \       / \      / \   /  \
 *   1   3   5   7   9   11     1   3    5   7 9   11
 */ 

测试程序输出

nrank=13的时候:

i=0;    u=-1,   d0=8,   d1=-1
    du=-1,  dd0=5,  dd1=-1
i=1;    u=2,    d0=-1,  d1=-1
    du=5,   dd0=3,  dd1=-1
i=2;    u=4,    d0=1,   d1=3
    du=3,   dd0=-1, dd1=-1
i=3;    u=2,    d0=-1,  d1=-1
    du=1,   dd0=4,  dd1=2
i=4;    u=8,    d0=2,   d1=6
    du=3,   dd0=-1, dd1=-1
i=5;    u=6,    d0=-1,  d1=-1
    du=13,  dd0=9,  dd1=1
i=6;    u=4,    d0=5,   d1=7
    du=7,   dd0=-1, dd1=-1
i=7;    u=6,    d0=-1,  d1=-1
    du=9,   dd0=8,  dd1=6
i=8;    u=0,    d0=4,   d1=12
    du=7,   dd0=-1, dd1=-1
i=9;    u=10,   d0=-1,  d1=-1
    du=5,   dd0=11, dd1=7
i=10;   u=12,   d0=9,   d1=11
    du=11,  dd0=-1, dd1=-1
i=11;   u=10,   d0=-1,  d1=-1
    du=9,   dd0=12, dd1=10
i=12;   u=8,    d0=10,  d1=-1
    du=11,  dd0=-1, dd1=-1

nrank=12的时候

i=0;    u=-1,   d0=8,   d1=-1
    du=11,  dd0=-1, dd1=-1
i=1;    u=2,    d0=-1,  d1=-1
    du=-1,  dd0=9,  dd1=-1
i=2;    u=4,    d0=1,   d1=3
    du=3,   dd0=-1, dd1=-1
i=3;    u=2,    d0=-1,  d1=-1
    du=5,   dd0=2,  dd1=4
i=4;    u=8,    d0=2,   d1=6
    du=3,   dd0=-1, dd1=-1
i=5;    u=6,    d0=-1,  d1=-1
    du=9,   dd0=3,  dd1=7
i=6;    u=4,    d0=5,   d1=7
    du=7,   dd0=-1, dd1=-1
i=7;    u=6,    d0=-1,  d1=-1
    du=5,   dd0=6,  dd1=8
i=8;    u=0,    d0=4,   d1=10
    du=7,   dd0=-1, dd1=-1
i=9;    u=10,   d0=-1,  d1=-1
    du=1,   dd0=5,  dd1=11
i=10;   u=8,    d0=9,   d1=11
    du=11,  dd0=-1, dd1=-1
i=11;   u=10,   d0=-1,  d1=-1
    du=9,   dd0=10, dd1=0
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352