假设我有这个模型:
class PhotoAlbum(models.Model):
title = models.CharField(max_length=128)
author = models.CharField(max_length=128)
class Photo(models.Model):
album = models.ForeignKey('PhotoAlbum')
format = models.IntegerField()
Run Code Online (Sandbox Code Playgroud)
现在,如果我想有效地查看相册子集中的一部分照片.我这样做:
someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related("photo_set")
for a in someAlbums:
somePhotos = a.photo_set.all()
Run Code Online (Sandbox Code Playgroud)
这只做了两个查询,这是我所期望的(一个是获得专辑,然后是一个像`SELECT*IN photos WHERE photoalbum_id IN().
一切都很棒.
但如果我这样做:
someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related("photo_set")
for a in someAlbums:
somePhotos = a.photo_set.filter(format=1)
Run Code Online (Sandbox Code Playgroud)
然后它做了大量的查询WHERE format = 1!我做错了什么或django不够聪明,意识到它已经取出所有的照片并可以在python中过滤它们?我发誓我在文档中的某个地方读到它本应该这样做......
任何人都可以给出一个示例或链接到一个__builtin_prefetch在GCC 中使用的示例(或者通常只是asm指令prefetcht0)以获得实质性的性能优势吗?特别是,我希望这个例子符合以下标准:
__builtin_prefetch指令会导致性能下降.__builtin_prefetch用相应的内存访问替换指令会导致性能下降.也就是说,我想要最简短的示例,显示__builtin_prefetch执行无需管理就无法管理的优化.
我想以编程方式禁用硬件预取.
从使用硬件实现的预取程序优化英特尔®酷睿™微体系结构上的应用程序性能以及 如何在32位英特尔®架构上选择硬件和软件预取,我需要更新MSR以禁用硬件预取.
这是一个相关的片段:
"DPL预取和L2流预取设置也可以通过编写设备驱动程序实用程序来更改
IA32_MISC_ENABLE寄存器中的位来以编程方式进行更改MSR 0x1A0.这样的实用程序可以启用或禁用预取机制,而无需任何服务器停机.
下表显示了IA32_MISC_ENABLE MSR为了控制DPL和L2流预取而必须更改的位:
Prefetcher Type MSR (0x1A0) Bit Value
DPL (Hardware Prefetch) Bit 9 0 = Enable 1 = Disable
L2 Streamer (Adjacent Cache Line Prefetch) Bit 19 0 = Enable 1 = Disable"
Run Code Online (Sandbox Code Playgroud)
我尝试使用http://etallen.com/msr.html,但这不起作用.我使用也试图wrmsr在asm/msr.h直接但段错误.我尝试在内核模块中执行此操作...并杀死了计算机.
顺便说一句 - 我使用的是内核2.6.18-92.el5并且它已MSR在内核中链接:
$ grep -i msr /boot/config-$(uname -r)
CONFIG_X86_MSR=y
...
Run Code Online (Sandbox Code Playgroud) 我知道关于这个主题的多个问题,但是,我没有看到任何明确的答案或任何基准测量.因此,我创建了一个简单的程序,它使用两个整数数组.第一个数组a非常大(64 MB),第二个数组b很小,适合L1缓存.程序迭代a并将其元素添加到b模块化意义上的相应元素中(当到达结束时b,程序从其开始再次开始).测量的不同大小的L1缓存未命中数b如下:
测量是在具有32 kiB L1数据高速缓存的Xeon E5 2680v3 Haswell型CPU上进行的.因此,在所有情况下,都b适合L1缓存.然而,大约16 kiB的b内存占用量大大增加了未命中数.这可能因为两者的负载预期a并b导致缓存线失效从一开始b在这一点上.
绝对没有理由保留a缓存中的元素,它们只使用一次.因此,我运行一个具有非时间负载a数据的程序变体,但未命中数没有改变.我还运行了一个非暂时预取a数据的变体,但仍然有相同的结果.
我的基准代码如下(没有显示非时间预取的变体):
int main(int argc, char* argv[])
{
uint64_t* a;
const uint64_t a_bytes = 64 * 1024 * 1024;
const uint64_t a_count = a_bytes / sizeof(uint64_t);
posix_memalign((void**)(&a), 64, a_bytes);
uint64_t* b;
const uint64_t b_bytes = atol(argv[1]) * 1024;
const uint64_t b_count = b_bytes …Run Code Online (Sandbox Code Playgroud) 我正在尝试预取训练数据以隐藏I/O延迟.我想编写自定义Python代码,从磁盘加载数据并预处理数据(例如,通过添加上下文窗口).换句话说,一个线程进行数据预处理,另一个线程进行训练.这在TensorFlow中可行吗?
更新:我有一个基于@ mrry的例子的工作示例.
import numpy as np
import tensorflow as tf
import threading
BATCH_SIZE = 5
TRAINING_ITERS = 4100
feature_input = tf.placeholder(tf.float32, shape=[128])
label_input = tf.placeholder(tf.float32, shape=[128])
q = tf.FIFOQueue(200, [tf.float32, tf.float32], shapes=[[128], [128]])
enqueue_op = q.enqueue([label_input, feature_input])
label_batch, feature_batch = q.dequeue_many(BATCH_SIZE)
c = tf.reshape(feature_batch, [BATCH_SIZE, 128]) + tf.reshape(label_batch, [BATCH_SIZE, 128])
sess = tf.Session()
def load_and_enqueue(sess, enqueue_op, coord):
with open('dummy_data/features.bin') as feature_file, open('dummy_data/labels.bin') as label_file:
while not coord.should_stop():
feature_array = np.fromfile(feature_file, np.float32, 128)
if feature_array.shape[0] == 0:
print('reach end of …Run Code Online (Sandbox Code Playgroud) Preload 和 prefetch 都用于提前请求资源,以便稍后的资源加载可以更快。两个好像可以互换
<link rel="preload" href="foo.js" as="script">
<link rel="prefetch" href="foo.js">
没有注意到任何区别。
它们的区别是什么?
我已经意识到Little's Law限制了在给定的延迟和给定的并发级别下数据传输的速度.如果您想更快地传输某些内容,则需要更大的传输,更多的"飞行中"传输或更低的延迟.对于从RAM读取的情况,并发性受到行填充缓冲区数量的限制.
当加载错过L1缓存时,将分配行填充缓冲区.现代英特尔芯片(Nehalem,Sandy Bridge,Ivy Bridge,Haswell)每个核心有10个LFB,因此每个核心限制为10个未完成的缓存未命中.如果RAM延迟为70 ns(似乎合理),并且每次传输为128字节(64B高速缓存线加上其硬件预取双线),则将每个内核的带宽限制为:10*128B/75 ns = ~16 GB/s.诸如单线程Stream之类的基准确认这是相当准确的.
减少延迟的显而易见的方法是使用x64指令(如PREFETCHT0,PREFETCHT1,PREFETCHT2或PREFETCHNTA)预取所需数据,这样就不必从RAM中读取数据.但是我无法通过使用它们加快速度.问题似乎是__mm_prefetch()指令本身消耗LFB,因此它们也受到相同的限制.硬件预取不会触及LFB,也不会跨越页面边界.
但我无法在任何地方找到任何记录.我发现的最接近的是15年前的文章,其中提到Pentium III上的预取使用Line Fill Buffers.我担心事情可能会发生变化.由于我认为LFB与L1缓存相关联,我不确定为什么L2或L3的预取会消耗它们.然而,我测量的速度与这种情况一致.
那么:有没有办法在没有使用这10个线路填充缓冲器中的一个的情况下从存储器中的新位置开始取出,从而通过绕过Little's定律实现更高的带宽?
看起来预取用法的一般逻辑是,如果代码忙于处理直到预取指令完成其操作,则可以添加预取.但是,似乎如果使用过多的预取指令,那么它会影响系统的性能.我发现我们需要先获得没有预取指令的工作代码.稍后我们需要在各种代码位置中进行预取指令的各种组合,并进行分析以确定由于预取而实际可能改进的代码位置.有没有更好的方法来确定应该使用预取指令的确切位置?
据我所知,硬件预取器至少会检测并通过内存获取持续的步幅.此外,它可以监控数据访问模式,无论真正意味着什么.这让我想知道,硬件预取程序是否会根据存储在内存中的实际数据做出决定,还是纯粹基于程序所展示的行为?
我问的原因是因为我偶尔会使用"非本地"指针作为指针.一个简单的例子就是预分配的东西数组,以及索引这个数组而不是指针的小整数.如果我需要存储大量这样的"指针",内存的节省可以快速增加,并通过使用更少的内存间接提高缓存性能.
但据我所知,这可能会干扰硬件预取器的工作方式.或不!
我可以想象,现实与否,预取单元检查进入L1缓存的缓存行以获取本机指针地址并开始将它们提取到L2或某些此类事物中.在那种情况下,我拯救记忆的聪明伎俩突然变得不那么聪明了.
那么,现代硬件预取器的作用是什么呢?他们可以被"非本地"指针绊倒吗?
正如大多数人所知,HTML5引入了一种称为链接预取的标准化浏览器机制,如果浏览器确定没有网络活动,则允许在后台预加载选择URL的内容.通过在头部添加以下内容来使用它:
<link rel="prefetch" href="http://www.example.com/">
Run Code Online (Sandbox Code Playgroud)
我很好奇这个机制是否也能可靠地用于XMLHttpRequest - 从某种意义上说,如果我指定一个链接预取,然后在同一页面上的某个时间启动一个AJAX请求,那么XHR是否是一个HTTP字节范围请求,或要求整个页面,有效地忽略部分预加载的页面?
用英语:AJAX请求也会受益于预加载或部分预加载的内容吗?