×

签到

分享到微信

打开微信,使用扫一扫进入页面后,点击右上角菜单,

点击“发送给朋友”或“分享到朋友圈”完成分享

CUDA转BANG C示例指南系列连载之四 编程模式示例 chap72021-01-19 18:13:21 回复 查看 BANG语言
CUDA转BANG C示例指南系列连载之四 编程模式示例
分享到:

写在前面

本篇接http://forum.cambricon.com/index.php?m=content&c=index&a=show&catid=33&id=681

在本篇中我们来看一看对向量的一些操作如何使用BANG C实现


二维数组转置

  • CPU code:

    for(int i=0;i<low_dim;i++){
        for(int j=0;j<high_dim;j++){
            output[i][j] = input[j][i];
        }}
  • BANG C code:

    // mlu可以通过__bang__transpose指令对片上的二维数组进行转置操作,// 但是需要二维数组的长和宽都对齐到128 byte.int align_len = 128 / sizeof(T);int align_high_dim = (high_dim + align_len - 1) / align_len * align_len;// 现将input数据拷贝到片上的nram空间中__memcpy(nram_input, input_addr, high_dim * low_dim * sizeof(float), GDRAM2NRAM);// 通过带步伐的拷贝操作memcpy,将nram_input(high_dim,low_dim)拷贝到nram_input_temp(align_high_dim, align_low_dim)__memcpy(nram_input_temp,nram_input, low_dim * sizeof(float), NRAM2NRAM,
            align_low_dim * sizeof(float), low_dim * sizeof(float), high_dim - 1);// 对nram_input_temp(align_high_dim, align_low_dim)进行转置操作得到nram_output_temp(align_low_dim, align_high_dim)__bang_transpose(nram_output, nram_input_temp, align_high_dim, align_low_dim);// 通过带步伐的拷贝操作memcpy,将nram_output_temp(align_low_dim, align_high_dim)拷贝到nram_output_temp(low_dim, high_dim)__memcpy(nram_output_temp,nram_input, high_dim * sizeof(float), NRAM2NRAM,
            align_high_dim * sizeof(float), low_dim * sizeof(float), low_dim - 1);// 最后将片上数据拷贝到output__memcpy(output_addr,nram_output_temp,high_dim * low_dim * sizeof(float), NRAM2GDRAM);

求一维向量最大值

  • CPU code:

    float max = -9999999.9;for(int i=0;i<count;i++){
        if(max<data[i]){
            max = data[i];
        }}
  • BANG C code:

    #define INF 9999999.0;#define ALIGIN_UP(x, num) (((x - 1) / num + 1) * num)#define ALIGN_DOWN_TO(x, num) (((x - 1) / num) * num//使用BANG C的__bang_max指令求出向量当中的最大值,存放在输入向量的首地址的位置。int count_up = ALIGIN_UP(count, 128);for (int i = count_up - 1; i > count; --i){
        data[i] = -INF;}__bang_max((float *)dst,(float *)data, count);float max = dst[0];unsigned int max_index = *((unsigned int*)(dst +1));

求二维向量中的高维度的最大值

  • CPU code:

    for(int i=0;i<low_dim;i++){
        float max = (-1)*INF;
        for(int j=0;j<high_dim;j++){
            if(max<input_data[i][j]){
                max = input_data[i][j];
            }
        }
        output_data[i] = max;}
  • BANG C code:

    //BANG C指令大多有对齐的要求,虽然不同的指令要求不一样,但是按照128对其,可以满足大部分指令的要求。int align_low_dim = ALIGIN_UP(low_dim, 128);//从DDR读取数据到片上nram空间__memcpy(nram_input, data_addr, low_dim * sizeof(float), GDRAM2NRAM,
            align_low_dim * sizeof(float), low_dim * sizeof(float), high_dim -1);//bang_maxpool是最大池化指令,功能比较复杂强大,其中一个基本功能就是可以求一个向量的最大值。__bang_maxpool(nram_output,nram_input,align_low_dim,high_dim,1,high_dim,1,1,1);//将计算完成的数据从片上拷回到ddr上。__memcoy(output_data, nram_output, low_dim * sizeof(float), NRAM2GDRAM);

一维向量求和

  • CPU code:

    T sum = 0.0;for(int i=0;i<count;i++){
        sum+=data[i];}
  • BANG C code:

    int align_len = 128 / sizeof(T);int repeat = count / align_len;//先按照128字节分段求和,将累加值存到向量起始128字节大小的位置。__bang_sumpool(temp_data, data, align_len,repeat,1,repeat,1,1,1);//对最后的128字节大小的数据进行求和。__bang_reduce_sum(dst, temp_data, align_len);T sum = dst[0];

对二维向量中的高维度规约

  • CPU code:

    for(int i=0;i<low_dim;i++){
        T sum = 0.0;
        for(int j=0;j<high_dim;j++){
            sum += input_addr[i][j];
        }
        output_addr[i] = sum;}
  • BANG C code:

    int align_low_dim = ALIGIN_UP(low_dim, 128);__memcpy(nram_input, input_addr, low_dim * sizeof(float), GDRAM2NRAM,
            align_low_dim * sizeof(float), low_dim * sizeof(float),high_dim -1);__bang_sumpool(nram_input, nram_input, align_low_dim, high_dim,1, high_dim,1,1,1);__memcoy(output_addr, nram_input, low_dim * sizeof(float), NRAM2GDRAM);

版权所有 © 2024 寒武纪 Cambricon.com 备案/许可证号:京ICP备17003415号-1
关闭