- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我是CUDA的新手。我正在研究基本的并行算法,例如归约,以了解线程执行的工作方式。我有以下代码:
__global__ void
Reduction2_kernel( int *out, const int *in, size_t N )
{
extern __shared__ int sPartials[];
int sum = 0;
const int tid = threadIdx.x;
for ( size_t i = blockIdx.x*blockDim.x + tid;
i < N;
i += blockDim.x*gridDim.x ) {
sum += in[i];
}
sPartials[tid] = sum;
__syncthreads();
for ( int activeThreads = blockDim.x>>1;
activeThreads > 32;
activeThreads >>= 1 ) {
if ( tid < activeThreads ) {
sPartials[tid] += sPartials[tid+activeThreads];
}
__syncthreads();
}
if ( threadIdx.x < 32 ) {
volatile int *wsSum = sPartials;
if ( blockDim.x > 32 ) wsSum[tid] += wsSum[tid + 32]; // why do we need this statement, any exampele please?
wsSum[tid] += wsSum[tid + 16]; //how these statements are executed in paralle within a warp
wsSum[tid] += wsSum[tid + 8];
wsSum[tid] += wsSum[tid + 4];
wsSum[tid] += wsSum[tid + 2];
wsSum[tid] += wsSum[tid + 1];
if ( tid == 0 ) {
volatile int *wsSum = sPartials;// why this statement is needed?
out[blockIdx.x] = wsSum[0];
}
}
}
if ( threadIdx.x < 32 )
条件和之后的代码是如何工作的。有人可以给出一个带有线程ID以及如何执行语句的直观示例吗?我认为理解这些概念很重要,因此任何帮助都将是有帮助的!
最佳答案
让我们看一下代码块,并一路回答您的问题:
int sum = 0;
const int tid = threadIdx.x;
for ( size_t i = blockIdx.x*blockDim.x + tid;
i < N;
i += blockDim.x*gridDim.x ) {
sum += in[i];
}
N
的数据集。为了理解的目的,我们可以做一个假设,即
N
>
blockDim.x*gridDim.x
,这最后一项只是网格中线程的总数。由于
N
大于线程总数,因此每个线程都将数据集中的多个元素相加。从给定线程的角度来看,它是求和元素的间隔,这些元素由线程的网格尺寸(
blockDim.x*gridDim.x
)隔开。每个线程将其总和存储在名为
sum
的局部(可能是寄存器)变量中。
sPartials[tid] = sum;
__syncthreads();
N
),它将其中间
sum
存储在共享内存中,然后等待该块中的所有其他线程结束。
for ( int activeThreads = blockDim.x>>1;
activeThreads > 32;
activeThreads >>= 1 ) {
if ( tid < activeThreads ) {
sPartials[tid] += sPartials[tid+activeThreads];
}
__syncthreads();
}
blockDim.x>>1
)中的一半线程开始,并使用这些线程中的每一个在共享内存中合并两个部分和。因此,如果我们的线程块从128个线程开始,则仅使用其中的64个线程将128个部分和减少为64个部分和。此过程在for循环中重复进行,每次将线程切成两半并合并部分和,每个线程每次两个。只要
activeThreads
> 32,该过程就会继续。因此,如果
activeThreads
为64,则这64个线程会将128个部分和合并为64个部分和。但是,当
activeThreads
变为32时,for循环终止,而没有将64个部分和合并为32。因此,在此代码块完成时,我们采用了(32个线程的任意倍数)线程块,并减少了许多部分和我们首先开始,直到64个。将256个部分和,128个部分和64个部分和相结合的过程必须在每次迭代时等待所有线程(在多个线程中)才能完成工作,因此
__syncthreads();
语句在for循环的每次遍历中执行。
if ( threadIdx.x < 32 ) {
__syncthreads();
,因为这将违反使用它的规则(所有线程都必须参与
__syncthreads();
)。
volatile int *wsSum = sPartials;
volatile
指针。从理论上讲,这告诉编译器不应进行各种优化,例如,将特定值优化到寄存器中。我们为什么以前不需要这个?因为
__syncthreads();
也带有
a memory-fencing function。
__syncthreads();
调用除了使所有线程彼此等待屏障之外,还强制所有线程更新返回共享或全局内存。但是,我们不再依赖于此功能,因为从现在开始,我们将不再使用
__syncthreads();
,因为我们已将自己(对于内核的其余部分)限制为一次扭曲。
if ( blockDim.x > 32 ) wsSum[tid] += wsSum[tid + 32]; // why do we need this
wsSum[tid] += wsSum[tid + 16]; //how these statements are executed in paralle within a warp
read the partial sum of my thread into a register
read the partial sum of the thread that is 16 higher than my thread, into a register
add the two partial sums
store the result back into the partial sum corresponding to my thread
wsSum[tid]
读入(本地线程)寄存器开始。这意味着线程0读取
wsSum[0]
,线程1读取
wsSum[1]
等。此后,每个线程将另一部分和读取到不同的寄存器中:线程0读取
wsSum[16]
,线程1读取
wsSum[17]
,等等。的确,我们不在乎
wsSum[32]
(及更高)值;我们已经将它们折叠到前32个
wsSum[]
值中。但是,正如我们将看到的,在此步骤中,只有前16个线程将有助于最终结果,因此前16个线程将把32个部分和组合成16个。接下来的16个线程也将起作用,但他们只是在做垃圾工作-它将被忽略。
wsSum[]
的前16个位置中。下一行代码:
wsSum[tid] += wsSum[tid + 8];
read the partial sum of my thread into a register
read the partial sum of the thread that is 8 higher than my thread, into a register
add the two partial sums
store the result back into the partial sum corresponding to my thread
wsSum[0..15]
)组合成8个部分和(包含在
wsSum[0..7]
中)。接下来的8个线程也将
wsSum[8..23]
合并为
wsSums[8..15]
,但是对8..15的写入是在线程0..8读取这些值之后发生的,因此有效数据不会被破坏。这只是额外的垃圾工作。对于经线内的其他8个线程块也是如此。因此,在这一点上,我们已将部分利息和合并为8个位置。
wsSum[tid] += wsSum[tid + 4]; //this combines partial sums of interest into 4 locations
wsSum[tid] += wsSum[tid + 2]; //this combines partial sums of interest into 2 locations
wsSum[tid] += wsSum[tid + 1]; //this combines partial sums of interest into 1 location
if ( tid == 0 ) {
volatile int *wsSum = sPartials;// why this statement is needed?
out[blockIdx.x] = wsSum[0];
}
关于cuda - 在关于warp同步线程执行工作原理的直觉上挣扎,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20382841/
我正在实现 IMAP 客户端,但 IMAP 邮箱同步出现问题。 首先,可以从 IMAP 服务器获取新邮件,但我不知道如何从邮箱中查找已删除的邮件。 我是否应该从服务器获取所有消息并将其与本地数据进行比
我研究线程同步。当我有这个例子时: class A { public synchronized void methodA(){ } public synchronized void met
嗨,我做了一个扩展线程的东西,它添加了一个包含 IP 的对象。然后我创建了该线程的两个实例并启动它们。他们使用相同的列表。 我现在想使用 Synchronized 来阻止并发更新问题。但它不起作用,我
我正在尝试使用 FTP 定期将小数据文件从程序上传到服务器。用户从使用 javascript XMLHttpRequest 函数读取数据的网页访问数据。这一切似乎都有效,但我正在努力解决由 FTP 和
我不知道如何同步下一个代码: javascript: (function() { var s2 = document.createElement('script'); s2.src =
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 7 年前。 Improve this qu
一 点睛 1 Message 在基于 Message 的系统中,每一个 Event 也可以被称为 Message,Message 是对 Event 更高一个层级的抽象,每一个 Message 都有一个
一 点睛 1 Message 在基于 Message 的系统中,每一个 Event 也可以被称为 Message,Message 是对 Event 更高一个层级的抽象,每一个 Message 都有一个
目标:我所追求的是每次在数据库中添加某些内容时(在 $.ajax 到 Submit_to_db.php 之后),从数据库获取数据并刷新 main.php(通过 draw_polygon 更明显)。 所
我有一个重复动画,需要与其他一些 transient 动画同步。重复动画是一条在屏幕上移动 4 秒的扫描线。当它经过下面的图像时,这些图像需要“闪烁”。 闪烁的图像可以根据用户的意愿来来去去和移动。它
我有 b 个块,每个块有 t 个线程。 我可以用 __syncthreads() 同步特定块中的线程。例如 __global__ void aFunction() { for(i=0;i #
我正在使用azure表查询来检索分配给用户的所有错误实体。 此外,我更改了实体的属性以声明该实体处于处理模式。 处理完实体后,我将从表中删除该实体。 当我进行并行测试时,可能会发生查询期间,一个实体已
我想知道 SQLite 是如何实现它的。它基于文件锁定吗?当然,并不是每个访问它的用户都锁定了整个数据库;那效率极低。它是基于多个文件还是仅基于一个大文件? 如果有人能够简要概述一下 sqlite 中
我想post到php,当id EmpAgree1时,然后它的post变量EmpAgree=1;当id为EmpAgree2时,则后置变量EmpAgree=2等。但只是读取i的最后一个值,为什么?以及如何
CUBLAS 文档提到我们在读取标量结果之前需要同步: “此外,少数返回标量结果的函数,例如 amax()、amin、asum()、rotg()、rotmg()、dot() 和 nrm2(),通过引用
我知道下面的代码中缺少一些内容,我的问题是关于 RemoteImplementation 中的同步机制。我还了解到该网站和其他网站上有几个关于 RMI 和同步的问题;我在这里寻找明确的确认/矛盾。 我
我不太确定如何解决这个问题......所以我可能需要几次尝试才能正确回答这个问题。我有一个用于缓存方法结果的注释。我的代码目前是一个私有(private)分支,但我正在处理的部分从这里开始: http
我对 Java 非常失望,因为它不允许以下代码尽可能地并发移动。当没有同步时,两个线程会更频繁地切换,但是当尝试访问同步方法时,在第二个线程获得锁之前以及在第一个线程获得锁之前再次花费太长时间(比如
过去几周我一直在研究java多线程。我了解了synchronized,并理解synchronized避免了多个线程同时访问相同的属性。我编写此代码是为了在同一线程中运行两个线程。 val gate =
我有一个关于 Java 同步的简单问题。 请假设以下代码: public class Test { private String address; private int age;
我是一名优秀的程序员,十分优秀!