向量化计算出现的异常问题



  • drivev.f:
           program NEKTON
    
           integer,parameter::N=24
           real,dimension(N,N)::a,c
           real,dimension(N,N)::b
    
           integer::start,finish
           call system_clock(start)
    
           call mxf8(a,N,b,N,c,N)
    
           call system_clock(finish)
           write(*,*) 't -s ',(finish-start)/10000.
    
           end
    
    mxm_stdv.f:  
          subroutine mxf8(a,n1,b,n2,c,n3)
    
          integer,parameter::N=24
          real::a(n1,N),b(N,n3),c(n1,n3)
          integer::i,j,k,error
          real::kt,x
    
          call random_seed()
    
          do k=1,100000
    
          do j=1,N
            do i=1,n1
                 call random_number(x)
                 a(i,j)=x
            enddo
          enddo
    
          do j=1,n3
            do i=1,N
                 call random_number(x)
                 b(i,j)=x
            enddo
          enddo
    
          c=0
          call my_slave(a,%val(n1),b,%val(n2),c,%val(n3))
    
          enddo
          end
    
    my_slavev.c:
    #include<stdio.h>
    #include<string.h>
    #include"simd.h"
    
    #define N 24
    #define NL24U24 576
    
    float *pa;
    float *pb;
    float *pc;
    
    int n11;
    int n22;
    int n33;
    void my_slave_(float* a,int n1,float* b,int n2,float* c,int n3)
    {
    
        int i,j,k;
        int ind,lima,limb,limc;
        float tmp[4];
        floatv4 fva,fvb,fvc,fvt;
    
        pa=a;
        pb=b;
        pc=c;
    
        n11=n1;
        n22=n2;
        n33=n3;
        int dd;
        if(n1 == n2)
        {
    
            for(j=0;j<n2;j++)
            {
                for(i=0;i<N;i++)
                {
                    limb=N*j;
                    limc=n1*j;
                    lima=(i+1)*n1;
    
                    simd_loade(fvb,b+limb+i);
                    for(k=i*n1,ind=0;k<lima;k+=4,ind+=4)
                    {
                        simd_load(fva,a+k);
                        fvc=fva*fvb;
                        simd_load(fvt,c+limc+ind);
                        fvc+=fvt;
                        simd_store(fvc,c+limc+ind);
                        //simd_store(fvc,&tmp[0]);
                        //memcpy(c+limc+ind,tmp,16);
                     }
                }
            }
        }
    
        return;
    }
    
    
    testv.sh:
    #!/bin/bash
    sw5f90 -host -I/usr/sw-mpp/mpi2/include -c  drivev.f
    sw5f90 -host -I/usr/sw-mpp/mpi2/include -c  mxm_stdv.f
    sw5cc -host  -msimd -O3 -c my_slavev.c
    
    #mpif90 drive.o athread_set_num_threads.o  athread_get_num_threads.o  mxm_std.o my_slave.o slave.o slave8.o DMA_getid.o reply_wait.o -L/path/to/xMath -lxMath -o exxO
    
    mpif90 drivev.o mxm_stdv.o my_slavev.o -o exxv
    

    这是我的程序脚本和文件,然后我出现了一个问题。如果我的程序的变量申明为real,float(单精度浮点数时),这个程序的运行时间才30秒,当我把程序改成double precision,double(双精度浮点数时)整个程序运行时间要10多分钟,问题在simd_store为什么会这么慢啊?这个向量化是不是有什么问题啊。



  • 1.不能单靠您现在测试就怀疑是simd_store的问题,建议分析一下程序,设计更多测试来确定具体的原因,注意测试的时候要保证测试环境是一致的,比如提交任务的节点。
    2.如果怀疑double类型的simd_store实现不好,可以改写成嵌汇编:
    #define my_simdstore(va,addr) asm volatile("vldd %0,0(%1)" : “=r”(va) : "r"(addr))
    试试。



  • 如果性能差别有这么大你可能需要确定一下你是不是每次提交时bsub都带了-b参数。



  • @夜深忽梦少年事 您好我提交的时候是有-b参数的。。可是我好像发现fortran编译器对double类型并没有对界处理啊。。。当我尝试使用 !$ align_symbol(symbol,32) 对数组处理一下,速度又正常了,可是这个声明只能用在common啊。。



  • @大笨象 是的,fortran手动向量化是申威特色功能,问题应该会比较多,毕竟ICC也不支持fortran手动向量化。



  • @夜深忽梦少年事 手动向量化?文档上也没这个东西噢,那我该怎么处理啊。。。我能不能在编译时让数组都自动对界啊 好像c一样。。



  • @大笨象 我的印象是sw5f90 -slave -msimd -mp的话定长数组可以自动对齐。



  • @popo 您好,请问您提供的这个嵌汇编语句可以在主核上使用吗?
    我试了一下这个语句,编译的时候报了
    Error: inappropriate arguments for opcode `vldd'
    这样的错误



  • @caiji 这个没测试过 ,但是手册应该由官方的向量化原语



  • @caiji 原因是主核上有浮点寄存器和整数寄存器的区别,可以试试:
    #define my_simdstore(va,addr) asm volatile("vldd %0,0(%1)" : “=f”(va) : "r"(addr))
    =f表示操作数是浮点寄存器。


登录后回复