我一直在试图解决这个问题大约一个月,我的C技能和我的谷歌都没有足够的力量来提出解决方案。
我最喜欢的一个侧面项目已经并将继续尝试通过反向和添加方法找到数字196的回文:
196 + 691 = 887
887 + 788 = 1675
一直持续到结果从前到后读取。
最近,我的选择方法是使用cuda,但我一遍又一遍地陷入困境。随身携带。
备份,我将内存中的数字表示为unsigned char数组,每个数字都是一个char - 所以基本上是解压缩的bcd。
__device__ __align__(4) unsigned char DigitArray[1024 * 1024];
部分和生成很容易并行。我将当前数字计数存储在设备存储器中,然后在每次迭代中存储:
__device__ int DigitCount;
__global__ void PartialSums()
{
int idx = GlobalThreadIndex();
int rev = DigitCount - (1 + idx);
unsigned char sum = DigitArray[idx];
__threadfence();
if(rev >= 0)
{
sum += DigitArray[rev];
}
DigitArray[idx] = sum;
}
一切都非常好。
现在进行携带 在一个完美的世界里,我希望发生以下事情:
__device__ unsigned int SumScratch[1024*256];
__global__ void Carry()
{
int idx = GlobalThreadIndex();
SumScratch[idx] = 0xF6F6F6F6;
__threadfence();
unsigned int * ptr = (unsigned int *)(DigitArray + (idx * size of(unsigned char));
SumScratch[idx] += *ptr;
__threadfence();
unsigned int cMask = __vcmples(SumScratch[idx], 0x0A0A0A0A);
unsigned int nCMask = ~cMask;
*ptr = __vadd4((SumScratch[idx] & cMask), __vsub4((SumScratch[idx] & nCMask), (OxF6F6F6F6 & nCMask)) & nCMask);
}
在这个完美的世界中,行
SumScratch[idx] += *ptr;
如果* ptr中的最高有效字节大于9,则会溢出到下一个字节。
虽然没有发生,所以指示的行可以替换为:
unsigned int val = *ptr;
unsigned int ret = 0;
unsigned int carryOut = 0;
asm("{"
"add.cc.u32 %0, %2, %3;"
"addc.cc.u32 %1, 0, 0;"
"}"
: "=r"(ret), "=r"(carryOut)
: "r"(val), "r"(OxF6F6F6F6)
);
SumScratch[idx] = 0;
__threadfence();
atomicAdd(&(SumScratch[idx]), ret);
atomicadd(&(SumScratch[idx+1]), carryOut);
随后是所有用于屏蔽的simd说明。
这个目标,如果你有: (大多数信号至少)
0x00090401 0x09090909 0x10081204
然后,最小的int的最重要的字节,当被添加到F6时将导致进入中间int的总和(活塞加到F6 ......所有字节都是FF)导致其全部位翻转为0并执行最重要的int。
所以,实际上,我想把整个数组视为只是一个二进制序列并允许位只是翻转。
非常感谢任何想法或想法。