首页
社区
课程
招聘
[讨论]关于并行大数加法的,遇到困境了...
发表于: 2009-12-29 16:19 6164

[讨论]关于并行大数加法的,遇到困境了...

2009-12-29 16:19
6164
有人知道大数加法的并行算法吗?或者资料也行。目前考虑向GPU上移植libtommath,不过刚开始就被卡住了... 并行的大数加法实在没有头绪。

大数加法的串行算法还好说,从低位向高位加就可以实现了,比如:
首先计算 a[0] + b[0],结果为 9+9=18,所以c[0]=18 % 10 = 8,进位=1
n ... 4 3 2 1 0
a | . . . . 8 9 |
+ b | . . . . 1 9 |
-------------------------
进位| 1 - |
c | 8 |

接着计算 a[1] + b[1] + 进位,比如这里的 8+1+1 = 10,所以 c[1] = 0,进位=1
n ... 4 3 2 1 0
a | . . . . 8 9 |
+ b | . . . . 1 9 |
-------------------------
进位| 1 1 - |
c | 0 8 |

依次往下计算直到结算完成


不过这个方法不能改成并行的,因为如果不知道低位的进位数值,就无法得出高位的结果c[i]

有人知道怎么并行计算加法吗?给个思路也行。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 292
活跃值: (70)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
我说一下我的思路,不知道可行否,还望大侠莫笑

第一步:
        9999999999
     +  9999999999
----------------------------
值      8888888888
进位    1111111111

第二步:
  进位左移1位 ,变为 11111111110
       8888888888
  +   11111111110
----------------------------
      19999999998
进位  00000000000

依次类推,直到进位全为0,结束。

2009-12-29 18:03
0
雪    币: 67
活跃值: (30)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
分段来算,然后再拼在一起可以吗?段内的进位在分段计算时计算,段间的进位拼合的时候算。
2009-12-29 18:53
0
雪    币: 232
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
感谢回复。这个方法我也想过,首先每个线程分别计算 a[i] + b[i],结果存入c[i],然后保存每一位的进位情况,再把进位并行的加回去(如果进位部分用串行从低位循环加上去,第一步的拆分就没有意义了)。

问题是不一定刚好结果是 8888888888 + 11111111110 这样不会出现二次进位的结果,最糟糕的莫过于:
假设每个线程负责竖着将每一位相加:
值 8888888898
进位 11111111110
------------------
新值 19999999908
进位2 00000000010

; 接着 进位2 左移变成
新值 19999999908
进位2 000000000100
------------------
新值 19999999008
进位3 00000000100

; 进位3左移... 进位结果一直不为零,这样就没完没了了 :(




嗯,分段计算可能是没有办法的办法。主要是怎么分段的问题,分过细了没有意义(比如一个n=2048的a[n],按4分段计算的话,段间还是需要循环512次),但是分太粗了又没有有效利用起GPU的计算能力(比如按64分段的话,只有32个线程在同时工作,在一些高档显卡上能并行的线程数远远大于这个)

而且本来设计上就利用了32位处理器计算的特点,a[n] 数组使用4字节的DWORD类型,这样计算 c[i] = a[i] + b[i] 的速度有所提升不说,进位处理的次数也会减少到1/4(相对于用BYTE存储来说)。

我对这个并行加法比较纠结的原因是因为加法是后面大多数计算的基础,这个速度上有细微提升都会对整个大数计算带来很大帮助。
希望大家畅所欲言
2009-12-29 18:53
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
假设每个线程负责竖着将每一位相加:
值 8888888898
进位 11111111110
------------------
新值 19999999908
进位2 00000000010

; 接着 进位2 左移变成
新值 19999999908
进位2 000000000100
------------------
新值 19999999008
进位3 00000000100

; 进位3左移... 进位结果一直不为零,这样就没完没了了 :(


对于这种情况,要是加一个对“9”的判断:前面是9,就前跳,找到前面最近的一个非9。再加上1,就不用太多的重复了。
2009-12-30 17:13
0
雪    币: 232
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
这个实现起来可能不是很方便,因为要是为了进位去操作别的线程负责的数据块(比如线程i为了进位,按你这个思路可能会去修改i+1、i+2、i+3...这些数据块),这个需要涉及读写同步的问题,因为可能 i+1 的线程刚计算出结果,还没写入 c[i+1] 里面,而低位线程i负责计算的 c[i] 发生进位,提前 c[i+1]++,这样数据就乱套了。
多线程限制其实也很多
2009-12-30 19:12
0
雪    币: 244
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
一个字节一个字节的加,一个CPU只有一个ALU,怎么可能是并行的呢?
2010-1-4 13:29
0
游客
登录 | 注册 方可回帖
返回
//