c++ - 多线程内联汇编

标签 c++ multithreading assembly openmp sparc

我正在尝试在 T4 机器上快速创建大量 sha256 哈希。 T4 有一条“sha256”指令,允许我在一个操作码中计算哈希值。我创建了一个内联汇编模板来调用 sha256 操作码:

在我的 C++ 代码中:

extern "C"
{
   void ProcessChunk(const char* buf, uint32_t* state);
}

pchunk.il:

.inline ProcessChunk,8  
.volatile
  /* copy state */
  ldd [%o1],%f0 /* load 8 bytes */ 
  ldd [%o1 + 8],%f2 /* load 8 bytes */ 
  ldd [%o1 +16],%f4 /* load 8 bytes */ 
  ldd [%o1 +24],%f6 /* load 8 bytes */ 

  /* copy data */
  ldd [%o0],%f8 /* load 8 bytes */ 
  ldd [%o0+8],%f10 /* load 8 bytes */ 
  ldd [%o0+16],%f12 /* load 8 bytes */ 
  ldd [%o0+24],%f14 /* load 8 bytes */ 
  ldd [%o0+32],%f16 /* load 8 bytes */ 
  ldd [%o0+40],%f18 /* load 8 bytes */ 
  ldd [%o0+48],%f20 /* load 8 bytes */ 
  ldd [%o0+56],%f22 /* load 8 bytes */ 

  sha256
  nop

  std %f0, [%o1]
  std %f2, [%o1+8]
  std %f4, [%o1+16]
  std %f6, [%o1+24]
.end

在单线程环境中运行良好,但速度不够快。我使用 openmp 来并行化应用程序,以便我可以同时调用 ProcessChunk。该应用程序的多线程版本适用于几个线程,但当我增加线程数(例如 16 个)时,我开始得到虚假结果。 ProcessChunk 函数的输入都是每个线程的本地堆栈变量。我已经确认无论线程数量如何,输入都能正确生成。如果我将 ProcessChunk 放入关键部分,我会得到正确的结果,但性能会显着降低(单线程性能更好)。我对问题可能出在哪里感到难过。 solaris 线程是否可以踩到另一个线程的浮点寄存器?

有什么办法可以调试吗?

问候

更新:

我更改了代码以使用四倍大小(16 字节)加载和保存:

.inline ProcessChunk,8
.volatile
  /* copy state */
  ldq [%o1],    %f0
  ldq [%o1 +16],%f4

  /* copy data */
  ldq [%o0],   %f8
  ldq [%o0+16],%f12
  ldq [%o0+32],%f16
  ldq [%o0+48],%f20

  lzd %o0,%o0
  nop

  stq %f0, [%o1]
  stq %f4, [%o1+16]
.end

乍一看,这个问题似乎已经消失了。在 32 个线程之后性能显着下降,所以这是我坚持使用的数字(至少目前)并且使用当前代码我似乎得到了正确的结果。我可能只是掩盖了这个问题,所以我将进行进一步的测试。

更新 2:

我找了一些时间回到这个问题上,并且我能够从 T4 中获得不错的结果(一分钟内达到数千万个哈希值)。

我所做的更改是:

  1. 使用汇编代替内联汇编
  2. 因为函数是叶函数,所以我没有触及注册窗口

我将所有内容打包到库中并提供代码 here

最佳答案

不是 Spark 架构专家(我可能是错的)但这是我的猜测:

您的内联汇编代码将堆栈变量加载到一组特定的浮点寄存器中,以便能够调用 sha 汇编操作。

这对两个线程如何工作?对 ProcessChunk 的两次调用都将尝试将不同的输入值复制到完全相同的 CPU 寄存器中。

我通常的看法是,asm 代码中的 CPU 寄存器就像高级编程语言的“全局”变量。

您的系统有多少个内核?在每个核心/一组硬件寄存器都有一个线程之前,您可能还不错。但这也意味着代码的行为可能取决于线程在系统不同内核上的调度方式。

您知道系统在 CPU 核心上调度来自同一进程的线程时的行为吗?我的意思是:系统是否存储未调度线程的寄存器,就像在上下文切换中一样?

我要运行的测试是生成数量等于 N 个 CPU 核心的线程,然后使用 N+1 运行相同的测试(我在这里的假设是每个 CPU 核心都有一个浮点寄存器集)。

关于c++ - 多线程内联汇编,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21491052/

相关文章:

c++ - 如何在 OpenCv 中轻松检测 2 个 ROI 是否相交?

c++ - 如何从成员函数中获取私有(private)数据? C++

multithreading - 如何使用 x264 编码器库计算优化的并行运行编码作业数量

c - 程序中的变量是否连续存储在内存中?

assembly - 延续(如 Smalltalk 中)和中断(如汇编器中)有什么区别?

c++ - Shedskin - 编译错误

c++ - 调用具有不同数量参数的函数

linux - x86-64 架构上的 gnu 汇编 RET 指令失败

java - 如何在Java中并行执行for-each循环中的语句?

java - 为什么在某些情况下,尽管进行了更新,但来自线程的更新不可见?