当我读ldd3时,我得到了关于内存屏障的概念,据说代码执行将被重新排序,原因就像缓存和编译优化一样。我认为没有依赖关系的代码可以重新排序以获得更好的性能,并且IO端口寄存器无法优化,因为它需要包含一致的数据。但是我无法理解下面的代码,是否有任何规则要遵循我应该在哪里插入smb(),mb(),barrier()等函数?
例如,在ldd3中的示例代码 short 。
import pandas as pd
import datetime
def parse_date(td):
resYear = float(td.days)/364.0 # get the number of years including the the numbers after the dot
resMonth = int((resYear - int(resYear))*364/30) # get the number of months, by multiply the number after the dot by 364 and divide by 30.
resYear = int(resYear)
return str(resYear) + "Y" + str(resMonth) + "m"
df = pd.DataFrame([("2000-01-10", "1970-04-29")], columns=["start", "end"])
df["delta"] = [parse_date(datetime.datetime.strptime(start, '%Y-%m-%d') - datetime.datetime.strptime(end, '%Y-%m-%d')) for start, end in zip(df["start"], df["end"])]
print df
start end delta
0 2000-01-10 1970-04-29 29Y9m
屏障之前的线如何以及屏障之后的线重新排序?我认为后者依赖于前者首先执行以获得 new 值。 这真让我感到困惑。
答案 0 :(得分:0)
使用内存屏障代替锁定以获得更好的性能。当存储器障碍提供所需的同步时,有几种标准模式。您可以从内核源代码中读取Documentation/memory-barriers.txt
。
在来自ldd3的给定示例中,障碍使用比平时少。在当前内核方面(与2.20+相反,在ldd3中描述),可以使用ACCESS_ONCE()
宏来表达相同的意图。
unsigned long new = *index + delta;
ACCESS_ONCE(*index) = (new >= (short_buffer + PAGE_SIZE)) ? short_buffer : new;
如果没有bariers,编译器可能会分配* index 两次:
*index = *index + delta;
if(*index > (short_buffer + PAGE_BUFFER)
*index = short_buffer;
因为*index
在多个线程中用作 unprotected invariant (它显示哪个缓冲区可用),所以将中间值*index + delta
写入其中会使其不变,其他人看到线程,不正确。这是由ACCESS_ONCE()宏阻止的,它强制编译器仅在被激发请求时才生成对变量的访问(写入)。
实际上,ACCESS_ONCE
(以及代码中的障碍)对于volatile
修饰符的变量是可还原的。