- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这里是 CUDA 的新手,但希望它的使用可以减少单线程 CPU 代码计算均方根所需的时间(具体来说,每个 u
连续不相交的 RMS长度为 v
的子数组包含在长度为 u*v
的数组 A
中,在 1 和 -1 之间 float 。
我曾希望使用 this示例来完成绝大多数工作*,但我发现即使是将 A
的子数组与 0
分开的第一步也是为了内存合并目的(这我正在通过单线程 CPU 代码进行)比使用“ballpark”值 u=200、v=5000 的整个基于 CPU 的 RMS 计算花费的时间更长!
我隐约意识到可能有一种方法可以同时应用填充 A
被复制到设备内存,因为我认为也许可以使用第二个内核来执行填充,但我不确定探索这些方法是否值得。我也知道 Thrust 和 cuBLAS,但在我简单的头脑中,链接的样本似乎更有可能提供所需的加速(假设必须小心准备内核输入)。
上面的“大概”值(类似于示例中的值)是否太小以至于无法让 GPU 发挥作用?唉,这两个数字都不太可能提高到 10 的下一个幂。非常感谢那些比我更熟悉 GPU 计算的人提供的任何意见。 FWIW,这是我试图改进的单线程 CPU 代码(rms
函数)和它的一些上下文:
const size_t num = 5000; // might be able to increase by a factor of <2
const size_t numSegs = 200; // might be able to increase by a factor of <5
float rms(const float a[], const size_t origin, const size_t length)
{
float sumOfSquares = 0.0f;
for (size_t i = 0; i < length; ++i)
sumOfSquares += a[origin + i] * a[origin + i];
return std::sqrt(sumOfSquares / float(length));
}
int main()
{
...
float* array = (float*)malloc(num * numSegs * sizeof(float));
float* RMSes = (float*)malloc(numSegs * sizeof(float));
// array fill omitted; A[i] lies between -1 and 1 inclusive
for (size_t segNum = 0; segNum < numSegs; ++segNum)
{
RMSes[segNum] = rms(array, segNum * num, num);
}
...
}
*假设 RMS(A)=sqrt(B/C),其中 B 是“A 点 A”,C 是 A 的长度
编辑:基于 CUDA 的方法确实有效,但目前比主机代码慢很多
编辑(再次):
objective-c PU:x86
目标 GPU:RTX3070(计算能力为 8.6 的“Ampere”)
执行时间:
在 main()
中循环(上图):2227-2259us(6 次运行)
使用 dot_product_avx2
在 main()
中循环 @Michael Roy 的回答:445-491us(3 次运行)
填充 array[]
:2279-3748us(6 次运行)
this 的第 119-134 行(不是通过 &hTimer
的行)+ 使用 h_C_GPU
计算 RMS:2050-2306us(3 次运行)
this 的第 119-134 行(不是通过 &hTimer
的行)+ 使用 h_C_GPU
without padding array[]
计算 RMS:2125-2382us (3运行)
看到填充对基于 GPU 的方法的影响如此之小,我感到非常惊讶(尽管示例建议“ElementN 强烈推荐为 warp 大小的倍数以满足内存合并的对齐约束”)
并行代码只是链接示例的最小修改版本。 VECTOR_N
对应于 u
,ELEMENT_N
对应于大于 v
且可被 warp 大小整除的最小数字, cudaMemcpyHostToDevice
只出现一次,A[i]
可能为负数,StopWatchInterface
相关代码省略,h_C_GPU
中的每个点积> 用于计算 RMS 值。
最佳答案
这是一个使用 Thrust/CUB 的实现。它应该作为您提出的任何 CUDA 解决方案的性能引用。由于 CUB 算法不知道问题的规律性,因此理论上完全可以编写比这个更快的 CUDA 实现。但在实践中,通过此引用获得显着加速可能非常重要。
这个问题完全适合 GPU 计算,但您的问题规模可能仍然太小,GPU 无法发挥作用。
我决定在这里使用 cub::DeviceSegmentedReduce
而不是 thrust::reduce_by_key
(在后端使用 CUB)以获得更好的性能,因为它更容易获得围绕测量分配临时存储的开销。
#include <cmath>
#include <iostream>
#include <cub/cub.cuh>
#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/iterator/transform_output_iterator.h>
#include <thrust/random.h>
#include <thrust/random/uniform_real_distribution.h>
constexpr size_t num = 5000; // might be able to increase by a factor of <2
constexpr size_t numSegs = 200; // might be able to increase by a factor of <5
template <typename T>
class ScaleBy
{
T factor_;
public:
ScaleBy(T factor) noexcept : factor_{factor} {}
__host__ __device__
T operator()(T val) const noexcept { return factor_ * val; }
};
template <typename T>
struct Square
{
__host__ __device__
T operator()(T val) const noexcept { return val * val; }
};
template <typename T>
class RootMean
{
T norm_;
public:
RootMean(T norm) noexcept : norm_{norm} {}
__host__ __device__
T operator()(T sum) const noexcept { return sqrt(sum / norm_); }
};
void segmented_rms_device(thrust::device_vector<float> const &d_array,
thrust::device_vector<float> &d_RMSes,
uint8_t *d_temp_storage,
size_t &temp_storage_bytes)
{
auto seg_size = d_array.size() / d_RMSes.size();
auto origin_iter = thrust::make_transform_iterator(
thrust::make_counting_iterator(0ull),
ScaleBy<size_t>{seg_size});
auto input_iter = thrust::make_transform_iterator(
d_array.cbegin(),
Square<float>{});
auto output_iter = thrust::make_transform_output_iterator(
d_RMSes.begin(),
RootMean<float>{static_cast<float>(seg_size)});
cub::DeviceSegmentedReduce::Sum(d_temp_storage,
temp_storage_bytes,
input_iter,
output_iter, numSegs,
origin_iter, origin_iter + 1);
}
float rms(thrust::host_vector<float> const &a, const size_t origin, const size_t length)
{
float sumOfSquares = 0.0f;
for (size_t i = 0; i < length; ++i)
sumOfSquares += a[origin + i] * a[origin + i];
return std::sqrt(sumOfSquares / float(length));
}
void segmented_rms_host(thrust::host_vector<float> const &array,
thrust::host_vector<float> &RMSes)
{
for (size_t segNum = 0; segNum < numSegs; ++segNum)
{
RMSes[segNum] = rms(array, segNum * num, num);
}
}
int main()
{
thrust::default_random_engine rng(123456789);
thrust::uniform_real_distribution<float> dist(-1.0f, 1.0f); // excludes 1.0f, but ok for testing
thrust::host_vector<float> array(num * numSegs);
thrust::host_vector<float> RMSes_ref(numSegs);
for (size_t i = 0ull; i < array.size(); ++i)
{
array[i] = dist(rng);
}
segmented_rms_host(array, RMSes_ref);
thrust::device_vector<float> d_array(array);
thrust::device_vector<float> d_RMSes(numSegs);
// Determine temporary device storage requirements
size_t temp_storage_bytes = 0;
segmented_rms_device(d_array, d_RMSes, nullptr, temp_storage_bytes);
// Allocate temporary storage
thrust::device_vector<uint8_t> d_temp_storage(temp_storage_bytes);
segmented_rms_device(d_array, d_RMSes,
thrust::raw_pointer_cast(d_temp_storage.data()), temp_storage_bytes);
thrust::host_vector<float> RMSes(d_RMSes);
for (size_t i = 0ull; i < numSegs; ++i)
{
if (std::abs(RMSes_ref[i] - RMSes[i]) / RMSes_ref[i] > 1.0e-4f)
{
std::cout << "Big deviation detected at i = " << i
<< ": RMS_ref = " << RMSes_ref[i]
<< " while RMS = " << RMSes[i] << '\n';
}
}
return 0;
}
关于c++ - CUDA 'dot product' 内核能否加速批量 RMS 计算?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75104734/
我正在使用 XCode 中的 SwiftUI 为 iPhone 编写应用程序。 在其中一个 View 中,有一个 Text 标签,每当按下按钮时都会更改其文本。 整个 View 是 Spring 动画
我有一个功能可以在生成报告时在弹出窗口中显示点点点。我想显示文本: 正在生成报告。生成报告..正在生成报告... ...重复,直到报告准备好。到目前为止,我只能在弹出窗口中获取三个点,而无法获取其他文
是否可以从 ... 中删除元素并将 ... 传递给其他函数?我的前两次尝试失败了: parent = function(...) { a = list(...) str(a) a$t
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
http://pastebin.com/index/9M2rA8cx那有我所有的代码。 您会注意到这两个 div 在 large.css 中居中。但是,文本在每个“。”之后重新居中。被申请;被应用。如
特殊文件 . 和 .. 是否实际存在并作为普通文件存储/位于文件系统中,或者它们是否仅在访问时解释/创建文件系统处理程序? .(当前目录) ..(父目录) 我的假设是它们不存在——否则,当您创建符号链
我想用...指示我想从 data.table 的自定义函数返回的变量目的。这是一个最小的可复制示例: library(data.table) d = data.table(mtcars) getvar
我想允许用户输入以下十进制或整数值 (A) .5 0.500 3 0 0.0 30 500000 4000.22 0. 这是我使用的以下正则表达式: factor: /^-?\d*[.]??\d*$/
我似乎明白 TLD 后的点无关紧要,例如: http://example.com/somepage/ == http://example.com./somepage/ (注意 TLD 后面的点) 我的
我试图用这个 DOT 输入文件创建一个简单的循环图: digraph { rankdir=LR; node0 [label = "0", group="bottom"]; n
我的问题与 this one 基本相同但给出的答案对我不起作用。 这是一个示例渲染 (source)和 compound=true; overlap=scalexy; splines=true; la
我正在尝试为作业问题制作一个点脚本生成器,它进行得很顺利,但我遇到了这个问题,其中一些未在子图中定义的节点被放置在其中。例如以下点脚本: digraph dg { compound=true;
我写了下面的 DOT 来生成图表。除了定义和布置的节点外,我想在标记为 L 的边缘的左侧和右侧放置一个节点,它们应该靠近 L,并且在 NODE3 和 NODE6 之间。 我尝试了一些不可见的节点。新节
我正在使用 python 和 matplotlib 来生成图形输出。 有没有一种简单的方法来生成点划线样式? 我知道 '--'、'-.' 和 ':' 选项。不幸的是,'-..' 不会产生点划线。 我查
给定以下字符串: "foo.bar.baz" 使用 Java String split 可以很容易地在“点”上分割它: split("foo.bar.baz", "\.") 但是,如果我想保留该点(如
有区别吗 import numpy as np np.dot(a,b) 和 a.dot(b) 内部?我找不到关于后一种方法的任何文档。 最佳答案 如果a 是一个数组,它们是等价的。您找不到关于 dot
有区别吗?如果不是,按惯例首选什么?性能似乎几乎相同。 a=np.random.rand(1000,1000) b=np.random.rand(1000,1000) %timeit a.dot(b)
如何使用 gvpr 将 DOT 语言中包含多个图形的文件拆分为多个 DOT 文件? 输入(1 个文件): # single.dot digraph one { a -> b; } digraph
RecursiveDirectoryIterator 似乎从本地主机和实时服务器给我两个不同的结果, define ('WEBSITE_DOCROOT', str_replace('\\', '/',
我有这样的例子: "hello . world . thanks ." 我想得到这个: "hello. world. thanks." 我试过了 text = text.replaceAll(" ."
我是一名优秀的程序员,十分优秀!