Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ warp如何与原子操作一起工作?_C++_C_Performance_Cuda_Atomic - Fatal编程技术网

C++ warp如何与原子操作一起工作?

C++ warp如何与原子操作一起工作?,c++,c,performance,cuda,atomic,C++,C,Performance,Cuda,Atomic,扭曲中的线程在物理上是并行运行的,因此如果其中一个线程(称为线程X)启动原子操作,另一个线程会做什么?等待这是否意味着,当线程X被推到原子队列时,所有线程都将等待,获取访问(互斥)并使用内存执行一些操作,这些内存受互斥的保护,然后再使用realese互斥 有没有办法让其他线程执行一些工作,比如读取一些内存,这样原子操作就会隐藏它的延迟?我是说,15个空闲线程。。我想不太好。原子能真的很慢,是吗?我怎样才能加速呢?有什么模式可以使用它吗 使用共享内存的原子操作会锁定一个存储库还是整个内存? 例如(

扭曲中的线程在物理上是并行运行的,因此如果其中一个线程(称为线程X)启动原子操作,另一个线程会做什么?等待这是否意味着,当线程X被推到原子队列时,所有线程都将等待,获取访问(互斥)并使用内存执行一些操作,这些内存受互斥的保护,然后再使用realese互斥

有没有办法让其他线程执行一些工作,比如读取一些内存,这样原子操作就会隐藏它的延迟?我是说,15个空闲线程。。我想不太好。原子能真的很慢,是吗?我怎样才能加速呢?有什么模式可以使用它吗

使用共享内存的原子操作会锁定一个存储库还是整个内存? 例如(没有mutex),有
uuu shared_uuuufloat smem[256]

  • Thread1运行
    atomicAdd(smem,1)
  • Thread2运行
    atomicAdd(smem+1,1)

这些线程使用不同的存储库,但通常使用共享内存。他们是运行parralel还是将排队?如果Thread1和Thread2来自分离的扭曲或普通扭曲,那么这个示例有什么不同吗?

我计算了大约10个问题。这使它很难回答。建议你每个问题问一个问题

一般来说,warp中的所有线程都在执行相同的指令流。因此,我们可以考虑两种情况:

  • 在这种情况下,如果没有条件(例如if…then…else),所有线程都在执行同一条指令,这恰好是一条原子指令。然后所有32个线程将执行一个原子线程,尽管不一定在同一位置。所有这些原子都将由SM处理,并在某种程度上进行序列化(如果它们正在更新相同的位置,它们将完全序列化)
  • 以条件句为例,假设我们有
    if(!threadIdx.x)AtomicAdd(*data,1)然后线程0将执行原子
    其他人不会。看起来我们可以让其他人去做
    其他一些,但是lockstep扭曲执行不允许这样。
    扭曲执行是序列化的,因此所有执行
    if
    (true)
    path将一起执行,所有执行
    if(false)
    path将同时执行,但true和false 路径将被序列化。所以再说一遍,我们真的不能有不同的 扭曲中的线程同时执行不同的指令
  • 它的网络是,在一个扭曲中,我们不能让一个线程做一个原子,而其他线程同时做其他事情

    您的许多其他问题似乎都期望内存事务在其产生的指令周期结束时完成。事实并非如此。对于全局和共享内存,我们必须在代码中采取特殊步骤,以确保其他线程可以看到以前的写事务(这可以被认为是事务完成的证据)。一种典型的方法是使用屏障指令,例如
    \uuuusyncthreads()
    \uuthreadfence()
    但如果没有这些屏障指令,线程就不会“等待”写入完成。(依赖于)读取的操作会使线程暂停。写操作通常不能暂停线程

    现在让我们看看您的问题:

    那么,如果其中一个启动原子操作,另一个会做什么呢?等等

    不,他们不会等的。原子操作被分派到SM上处理原子的一个功能单元,所有线程一起以锁步方式继续。因为原子通常意味着读取,是的,读取会使扭曲停止。但是线程不会等到原子操作完成(即写操作)后才执行。但是,对该位置的后续读取可能会再次暂停扭曲,等待原子(写入)完成。在保证更新全局内存的全局原子的情况下,如果原始SM(如果启用)中的L1和L2包含该位置作为条目,则会使其无效

    有没有办法让其他线程执行一些工作,比如读取一些内存,这样原子操作就会隐藏它的延迟

    不完全是,因为我在开始时说的原因

    原子能真的很慢,是吗?我怎样才能加速呢?有什么模式可以使用它吗

    是的,如果原子控制了活动(如简单的缩减或简单的历史规划),原子可以使程序运行得慢得多。一般来说,加速原子操作的方法是不使用它们,或者以不控制程序活动的方式少用它们。例如,一个简单的约简将使用一个原子将每个元素添加到全局和中。智能并行还原将完全不使用原子来完成threadblock中的工作。在threadblock缩减结束时,可以使用单个原子将threadblock部分和更新为全局和。这意味着我可以用32个或更少的原子加法快速并行减少任意数量的元素。原子的这种节省使用基本上不会在整个程序执行中引起注意,除非它能够在单个内核调用而不是2个内核调用中完成并行缩减

    共享内存:它们是运行parralel还是将排队

    他们将排队。这是因为可以在共享内存上处理原子操作的功能单元数量有限,不足以在一个周期内处理来自warp的所有请求

    我避免回答与原子操作吞吐量相关的问题,因为AFAIK文档中没有很好地指定这些数据。这可能是因为,如果您同时或几乎同时发出足够多的原子操作,则某些扭曲将在原子指令上暂停,这是由于这些操作所占用的队列造成的