尝试使用 cpp 线程并行化 NTT

问题描述

这是我第一次在这里提问,如果有什么问题请见谅。
我正在尝试使用 cpp 线程并行化 NTT,但我只是在这里迷路了。我基于解释 NTT 的 CUDA 并行化的文章编写了代码并对其进行了修改,因此它对处理器(更少的线程)更有意义,但是我碰壁了,无法进行。 基本上,创建了一个类来映射每个线程与数组中需要制作蝴蝶的元素对,结果是错误的,并且 psis 似乎计算正确(位相反的顺序)。
我'我是并行计算和 NTT 的新手,感谢您的帮助。

class threadInfo {
    public:
        std::vector<long long *> psi,u,v;
        void clear(){
            psi.clear();
            u.clear();
            v.clear();
        }
};

void threadButterfly(threadInfo info,long long mod,bool invert){
    for (long long i = 0; i < info.u.size(); i++)
    {
        long long u = * info.u[i],v = * info.v[i];
        if(!invert)     v = modulo(v* * info.psi[i],mod);
        * info.u[i] = modulo(u+v,mod);
        * info.v[i] = modulo(u-v,mod);
        if(invert)      * info.v[i] = modulo((u-v)* * info.psi[i],mod);
        else            * info.v[i] = modulo(u-v,mod);
    }
}

void threadSched(vector<long long> &a,long long len,std::vector<long long> &psi,vector<threadInfo> info,bool invert){
    vector<thread> threads(THREAD_NUM);
    long long n = a.size();
    for (long long id = 0; id < n>>1; id++)                                 //puts each u and v pairs in each thread object
    {
        long long step = (a.size()/len)/2;                                  // step counts the distance between u and v
        long long psi_step = id/step;                                       // what k in psi**k to use relative to the first in the group
        long long target = (psi_step * step * 2) + (id % step);             // what u and v we want
        long long group = len + psi_step;                                   // what k in psi**k to use relative to all psis
        long long arrayid = floor((2*id*THREAD_NUM)/n);                     // what thread will the par go to
        info[arrayid].psi.push_back( & psi[group]);
        info[arrayid].u.push_back( & a[target]);
        info[arrayid].v.push_back( & a[target+step]);
    }
    for ( size_t id=0; id<THREAD_NUM; id++ )        threads[id] = thread(threadButterfly,info[id],mod,invert);
    for ( size_t id=0; id<THREAD_NUM; id++ )        threads[id].join(); 
    for ( long long i = 0; i<info.size(); i++ )     info[i].clear();
    if(invert)  for ( long long j = 0; j < n; j++ ) a[j]=modulo(a[j]*mod_in(n,mod),mod);
}

void ntt(vector<long long> &a,vector<long long> &psi){
    vector<threadInfo> fwd(THREAD_NUM);
    for (long long len = 1; len < a.size(); len = 2 * len)
    {
        threadSched(a,len,psi,fwd,false);
    }
}

void intt(vector<long long> &a,vector<long long> &psi){
    vector<threadInfo> rev(THREAD_NUM);
    for (long long len = 1; len < a.size(); len = 2 * len)
    {
        threadSched(a,rev,true);
    }
}

感谢关注。
编辑1:
解释得更好一点,数论变换基本上是一个傅立叶变换,在一个以模为界的域中带有整数,它改变了多项式的表示(例如:6x^2 + 5x +9)从 x-power=index([ 9,5,6]) 到 {x,y}={index,variable}([9,20,26]) 以便我们可以更快地乘以多项式。要做到这一点,我们需要原始根(代码中的 psis)及其幂,它们基于多项式的大小及其模。
Ntt里面是一个butterfly操作,论文把这个操作里面的数组元素分给了gpu的每个线程,所以为了cpus修改,我创建了一个类来符号化每个线程,给每个线程传递SIZEOFpolyNOMIAL/TH​​READNUMBER元素.当线程被调用时,它会为其给定的元素数组计算蝴蝶
我正在使用 gcc -O3 -std=c++17 -pthread -march=native -lm 并且我正在使用各种实现测试 NTT,唯一一个不起作用的是这个一个所以主要功能(这是巨大的)在这种情况下并不重要,只会使这篇文章变得臃肿。
论文:https://eprint.iacr.org/2021/124.pdf

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)