我有兴趣掌握与预取相关的功能,如
_mm_prefetch(...)
因此,当我执行循环遍历数组的操作时,内存带宽得到充分利用.了解这一点的最佳资源是什么?
我正在使用英特尔Linux平台上的GCC 4系列在C中完成这项工作.
当从连续的内存位置执行一系列_mm_stream_load_si128()调用(MOVNTDQA)时,硬件预取器是否仍会启动,或者我应该使用显式软件预取(使用NTA提示)以获得预取的好处,同时仍然避免缓存污染?
我问这个的原因是因为他们的目标似乎与我相矛盾.流加载将获取绕过缓存的数据,而预取器尝试主动将数据提取到缓存中.
当顺序迭代一个大型数据结构(处理过的数据不会在很长一段时间内被修饰)时,我有必要避免污染chache层次结构,但我不想因频繁出现频繁的~100次循环处罚-fetcher闲置.
目标架构是Intel SandyBridge
我正在使用新prefetchDataSource的UITableView(也可以应用于UICollectionView.我遇到的问题如下:
我正在实施func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath])哪个工作得很好.
我使用的array是以15个元素开头的.所以numberOfRowsInSection最初将返回array.count15.
我想要的是prefetchRowsAt函数告诉我当我们从行中运行时,以便从我自己的源获取新数据,将这些数据附加到array然后reloadData(),这将反过来增加numberOfRowsInSection.
prefetchRowsAt不会超出第15行,因为它受到numberOfRowsInSection我指定的限制.基本上,我卡住了.基本上,当我在第5行时,我希望它告诉我开始预取第16行.我尝试和工作的一个解决方案是将计数numberOfRowsInSection增加到100,然后在我获取新数据时放置占位符单元格.但滚动条看起来太小,因为它预计有100个项目,所以UX不会那么好.
也许我在第3步中使用的模式是错误的(附加到数组和reloadData)?或者你能想到另一个更清洁的问题解决方案吗?
提前致谢!
我有一个React应用程序,其中的组件根据用户输入加载不同的视频.只有4或5个小视频,因此我想在浏览器处于非活动状态时预取所有这些视频.
在我的组件中,我有:
<video src={this.props.video} type="video/mp4" />
Run Code Online (Sandbox Code Playgroud)
在我的index.html中,我在视频中有一条线:
<link rel="prefetch" as="video/mp4" href="link/to/my/video.mp4">
Run Code Online (Sandbox Code Playgroud)
但是,这不起作用.查看控制台,我可以看到视频已被提取(状态为200)但未存储在缓存中(响应大小为5 Mb,磁盘为0 Mb).当我提供用户输入并且组件需要显示该视频时,它将再次获取,这需要几秒钟.
PS - 我没有尝试在视频元素上使用预加载的原因是因为预加载仅在您正在查看的页面中包含视频时才有效.在我的情况下,我想加载视频,即使它们不是当前页面所必需的.
更新:我做了一支笔,你可以看到尽管在头部使用了链接标签,但视频并未预先获取.
我有一个非常简单的方法UICollectionView,它使用组合布局来轻松实现动态单元格高度。不幸的是,这样做似乎禁用了使用UICollectionViewDataSourcePrefetching. 在以下示例代码中,该collectionView(_:prefetchItemsAt:)方法仅在初始显示集合视图时调用一次。没有滚动操作会导致对方法的进一步调用。
我该怎么做才能使预取工作?
class ViewController: UIViewController,
UICollectionViewDataSource,
UICollectionViewDelegate,
UICollectionViewDataSourcePrefetching
{
@IBOutlet var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.collectionViewLayout = createLayout()
collectionView.dataSource = self
collectionView.delegate = self
collectionView.prefetchDataSource = self
collectionView.register(MyCell.self, forCellWithReuseIdentifier: "cell")
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 100
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MyCell
cell.label.text = String(repeating: "\(indexPath) ", count: indexPath.item) …Run Code Online (Sandbox Code Playgroud) 据我所知,Fermi GPU支持预取L1或L2缓存.但是,在CUDA参考手册中我找不到任何关于它的东西.
Dues CUDA允许我的内核代码预取特定数据到特定级别的缓存?
英特尔有助于提供预取编译指示; 例如
#pragma prefetch a
for(i=0; i<m; i++)
a[i]=b[i]+1;
Run Code Online (Sandbox Code Playgroud)
将由a编译器确定预先获取一定数量的循环周期.
但是如果a不是一个数组而是一个[]被覆盖的类呢?如果operator[]一个简单的数组访问,可以预取仍然以这种方式使用?
(据推测这个问题也适用于此std::vectors).
出于好奇,我试图测试List<T>使用两者value和reference类型的性能.
结果并不像我预期的那样,让我相信我对这些对象在内存中如何布局的理解可能不正确.
这是我的实验:
创建一个class只包含两个成员的基本,a int和abool
创建2个List<T>对象来保存我的测试类(List1和List2)
随机生成的测试对象并将其添加到List1和List2交替
时间迭代需要多长时间List1(执行一些任意工作,例如递增计数器然后访问元素)
然后我重复了一个struct代替class
我的假设是,当使用a时class,其中的引用List<T>将是连续的,但由于我如何创建它们(在添加到List1和之间切换List2),它们指向的对象可能不会.
我认为当使用a时struct,因为它是一个值类型,所以对象本身将在内存中连续List<T>保持(因为它保存实际的项而不是引用的集合).
因此,我期望struct表现更好(由于预取器等...)
实际上,两者都非常相似.
这里发生了什么?
编辑 - 添加了实际访问迭代器中元素的代码,包括代码示例
测试类(或结构)
public class/struct TestClass
{
public int TestInt;
public bool TestBool;
}
Run Code Online (Sandbox Code Playgroud)
创建随机列表:
var list1 = new List<TestClass>();
var list2 = new List<TestClass>();
var …Run Code Online (Sandbox Code Playgroud) 英特尔编译器在循环内生成以下预取指令,以通过a_ptr指针访问数组:
400e93: 62 d1 78 08 18 4c 24 vprefetch0 [r12+0x80]
Run Code Online (Sandbox Code Playgroud)
如果我手动更改(通过十六进制编辑可执行文件)这到非临时预取:
400e93: 62 d1 78 08 18 44 24 vprefetchnta [r12+0x80]
Run Code Online (Sandbox Code Playgroud)
循环运行快了近1.5倍(!!!).但是,我更喜欢编译器为我生成非时间预取.我以为
#pragma prefetch a_ptr:_MM_HINT_NTA
Run Code Online (Sandbox Code Playgroud)
在循环之前应该做的伎俩,但它实际上没有; 它生成的指令与不完整的pragma完全相同.为什么icpc忽略这个pragma?我怎么强迫它生成非时间预取?
选择.据我所知,报告没有说任何有用的内容:
LOOP BEGIN at test-mic.cpp(56,5)
remark #15344: loop was not vectorized: vector dependence prevents vectorization
remark #15346: vector dependence: assumed ANTI dependence between b_ptr line 64 and b_ptr line 65
remark #15346: vector dependence: assumed FLOW dependence between b_ptr line 65 and b_ptr line …Run Code Online (Sandbox Code Playgroud) 使用__builtin_prefetch(..., 1)内部函数(准备写入时的预取)完成后期预取的成本是多少?也就是说,在需求加载或写入需要它之前没有到达L1缓存的预取?
例如
void foo(std::uint8_t* line) {
__builtin_prefetch(line + std::hardware_constructive_interference_size, 1);
auto next_line = calculate_address_of_next_line(line);
auto result = transform(line);
write(next_line, result)
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,如果成本transform低于预取,那么这个代码最终会比没有预取的效率低吗?关于缓存预取的维基百科文章讨论了for循环的最佳步幅,但未提及该场景中次优预取的影响(例如,如果k太低会发生什么?).
这是否足够流水线以至于次优预取无关紧要?出于这个问题的目的,我只考虑Intel x86(Broadwell时代的处理器).