正 文

64位程序开发中的性能优化技巧


www.7dspace.com  更新日期:2006-2-25 4:55:14  七度空间


  算法优化及二进制位距

  另一个可进行64位优化之处是在位串中计算(二进制)位距。二进制位距常用于进行分类与查找对象的相似之处的数据采集与AI(人工智能)程序,其通常表示为二进制描述符(位串)。此处优化的重点是位距算法,因为它会在系统中每对对象之间重复执行。

  最知名的位距度量算法是加重平均位距,其是位中的一个最小数,并能被改变以转换为另一个位串。换句话来说,你可以使用XOR位运算符来结合位串,并利用得到的结果计算出位数。

  如例7中采用了如上算法的程序,最明显的优化之处是去掉了临时位集,并同时计算XOR与总数量。而临时文件的产生是C++编译器的"内部运动",且因为内存的复制与重分配,降低了程序效率,请看例8:

  例7:

#include <bitset>
using namespace std;

const unsigned BSIZE = 1000;
typedef bitset<BSIZE> bset;

unsigned int humming_distance(const bset& set1, const bset& set2)
{
 bset xor_result = set1 ^ set2;
 return xor_result.count();
}

  例8:

{
 unsigned int hamming;
 int a1[2048];
 int a2[2048];
 long long* pa1;
 long long* pa2;

 pa1 = (long long*) a1; pa2 = (long long*) a2;
 hamming = 0;

 for (int i = 0; i < sizeof(a1) / sizeof(long long); ++i)
 {
  long long b;
  b = pa1[i] ^ pa2[i];

  b = (b & 0x5555555555555555LU) + (b >> 1 & 0x5555555555555555LU);
  b = (b & 0x3333333333333333LU) + (b >> 2 & 0x3333333333333333LU);
  b = b + (b >> 4) & 0x0F0F0F0F0F0F0F0FLU;
  b = b + (b >> 8);
  b = b + (b >> 16);
  b = b + (b >> 32) & 0x0000007F;

  hamming += b;
 }
}

  这种优化立竿见影地达到了几个目标:与内存通信量的减少、更好地复用了寄存器,当然,最重要的是64位并行处理(参见图3)。此结果的本质是改进了CPU操作与内存负载的平衡,这是通过结合例3与例4的算法来达到的。


图3

  这种优化技术还能作进一步的扩展,以用作任何"逻辑操作或位计数"的位距度量。其令人感兴趣之处在于,如Tversky Index、Tanamoto、Dice、Cosine函数等等更复杂的度量方法,现在也能更容易表达了。

  为了进一步加深理解,来看一下Tversky Index:

TI = BITCOUNT(A & B) / [a*(BITCOUNT(A-B) + b*BITCOUNT(B-A) + BITCOUNT(A & B)]

  公式中包含了三个操作,BITCOUNT_AND(A, B)、BITCOUNT_SUB(A, B)、BITCOUNT_SUB(B, A)。三个操作能被结合成一条流水线操作,见图4。这种技术改进了数据存储位置,更好的复用了CPU缓存,也意味着减少CPU延迟及提高程序性能,见例9:

  例9:

{
 double ti;
 int a1[2048];
 int a2[2048];
 long long* pa1;
 long long* pa2;

 pa1 = (long long*) a1; pa2 = (long long*) a2;
 ti = 0;

 for (int i = 0; i < sizeof(a1) / sizeof(long long); ++i)
 {
  long long b1, b2, b3;
  b1 = pa1[i] & pa2[i];
  b2 = pa1[i] & ~pa2[i];
  b3 = pa2[i] & ~pa1[i];

  b1 = popcount(b1);
  b2 = popcount(b2);
  b3 = popcount(b3);

  ti += double(b1) / double(0.4 * b2 + 0.5 * b3 + b1);

 }
}


图4

  64位之后还有什么?

  上述的大多数算法都能通过基于矢量的指令加以编码--如单指令多数据(SIMD)。带有SIMD功能的CPU含有特殊的扩展寄存器(64位或128位)或执行单元,能一次载入几个机器字,并对它们进行一些并行的操作。最流行的SIMD引擎是Intel的SSE;AMD的3DNow!;Motorola、Apple、IBM的AltiVec。SIMD寄存器与通用寄存器不同,它们不允许你执行诸如IF这样的流量控制操作,这也使SIMD编程更加困难。不难看出,基于SIMD代码的可移植性也是有限的。可是,一个并行的64位优化算法能在概念上很容易地被转换为一个128位的SIMD算法;请参见例10,其使用SSE2指令集实现了一个XOR算法,此处使用了Intel C++编译器的内部兼容性。
 
  例10:

void bit_xor(unsigned* dst, const unsigned* src, unsigned block_size)
{
 const __m128i* wrd_ptr = (__m128i*)src;
 const __m128i* wrd_end = (__m128i*)(src + block_size);
 __m128i* dst_ptr = (__m128i*)dst;

 do
 {
  __m128i xmm1 = _mm_load_si128(wrd_ptr);
  __m128i xmm2 = _mm_load_si128(dst_ptr);

  __m128i xmm1 = _mm_xor_si128(xmm1, xmm2);
  __mm_store_si128(dst_ptr, xmm1);
  ++dst_ptr;
  ++wrd_ptr;

 } while (wrd_ptr < wrd_end);
}

  既然在64位上数值优化有这些好处,那你还等什么呢?

3页,页码:[1] [2] [3] 

上一篇:在Visual Studio 2005中实现VB重构
下一篇:CSS实现完美垂直居中
64位程序开发中的性能优化技巧 作者:谢启东编译 来源:天极网
收藏此页】【打印】【关闭
站 内 搜 索
 

热 点 导 读
特 别 推 荐