OCaml GC强制执行全局锁定,以防止mutators(线程)并行运行,尽管它们可以并发运行(交错).我相信SML/NJ和MLton也是如此,但不是PolyML,GHC,F#,Clojure和Scala.
还有哪些其他功能语言实现允许线程并行运行?
以下测试代码(F#)未返回我期望的结果:
let safeCount() =
let n = 1000000
let counter = ref 0
let spinlock = ref <| SpinLock(false)
let run i0 i1 () =
for i=i0 to i1-1 do
let locked = ref false
try
(!spinlock).Enter locked
if !locked then
counter := !counter + 1
finally
if !locked then
(!spinlock).Exit()
let thread = System.Threading.Thread(run 0 (n/2))
thread.Start()
run (n/2) n ()
thread.Join()
!counter
Run Code Online (Sandbox Code Playgroud)
我希望SpinLock相互排除计数器,因此,它返回1,000,000的计数,但相反,它返回较小的值,好像没有发生互斥.
有什么想法有什么不对吗?
我有一个用C++编写的小型原型程序,在Linux下运行,使用该memalign函数来分配与页面等边界对齐的区域.在Visual C++中是否有等效的功能?
我有一个沿边缘流量的有向图,我想通过删除所有循环流来简化它.这可以通过在任何给定循环中找到沿每个边缘的最小流量并且将循环中每个边缘的流量减少该最小体积来完成,从而删除具有零流量的边缘.当所有循环流都被移除后,图形将是非循环的.
例如,如果我有顶点A,B和C,其中从A→B,2从B→C和3从C→A的1流动的图表然后我可以从A→B,1从没有流重写这个B→C和2→C→A.图中的边数从3减少到2,结果图是非循环的.
哪种算法(如果有的话)可以解决这个问题?
我正在学习x86汇编程序以编写编译器.特别是,我正在使用各种简单的递归函数并通过不同的编译器(OCaml,GCC等)提供它们,以便更好地理解不同编译器生成的汇编程序的种类.
我有一个简单的递归整数Fibonacci函数:
int fib(int x) { return (x < 2 ? x : fib(x-1)+fib(x-2)); }
Run Code Online (Sandbox Code Playgroud)
我的手工编码组件看起来像这样:
fib:
cmp eax, 2
jl fin
push eax
dec eax
call fib
push eax
mov eax, [esp+4]
add eax, -2
call fib
add eax, [esp]
add esp, 8
fin:
ret
Run Code Online (Sandbox Code Playgroud)
使用Intel-syntax汇编程序编译该函数gcc -O2会产生这个神秘的代码:
_fib:
push edi
push esi
push ebx
sub esp, 16
mov edi, DWORD PTR [esp+32]
cmp edi, 1
jle L4
mov ebx, edi
xor esi, esi
L3:
lea eax, [ebx-1] …Run Code Online (Sandbox Code Playgroud) 灵感来自Herb Sutter引人注目的演讲不是你父亲的C++,我决定再使用微软的Visual Studio 2010来看看最新版本的C++.我特别感兴趣的是Herb断言C++是"安全的",因为我没有听说过C++ 11解决了众所周知的向上funarg问题.据我所知,C++ 11无法解决这个问题,因此不"安全".
您不希望返回对局部变量的引用,因为本地是在函数返回后将不再存在的堆栈帧上分配的,因此,该函数将返回一个悬挂指针,指向已分配的内存,这将导致非 - 确定数据损坏.C和C++编译器知道这一点,并在您尝试将引用或指针返回到本地时发出警告.例如,这个程序:
int &bar() {
int n=0;
return n;
}
Run Code Online (Sandbox Code Playgroud)
导致Visual Studio 2010发出警告:
warning C4172: returning address of local variable or temporary
Run Code Online (Sandbox Code Playgroud)
但是,C++ 11中的lambdas可以很容易地通过引用捕获局部变量并返回该引用,从而产生等效的悬空指针.考虑以下函数foo返回一个lambda函数,该函数捕获局部变量n并返回它:
#include <functional>
std::function<int()> foo(int n) {
return [&](){return n;};
}
Run Code Online (Sandbox Code Playgroud)
这种看似无害的功能是内存不安全和损坏数据的来源.调用此函数将lambda放在一个位置然后调用lambda并在另一个地方打印它的返回值为我提供了这个输出:
1825836376
Run Code Online (Sandbox Code Playgroud)
此外,Visual Studio 2010不提供任何警告.
对我来说,这看起来像是一个非常严重的设计缺陷.即使是最简单的重构也可能会产生一个lambda交叉堆栈帧,无声地引入非确定性数据损坏.然而,似乎有关于这个问题的宝贵信息很少(例如,在StackOverflow上搜索"向上funarg"和C++没有提供命中).人们是否意识到这一点?有人在研究解决方案或描述变通方法吗?
考虑以下程序:
for i=1 to 10000000 do
z <- z*z + c
Run Code Online (Sandbox Code Playgroud)
在哪里z和c是复杂的数字.
使用x87 vs SSE和单对双精度算法,该程序的高效x86汇编程序实现是什么?
编辑我知道我可以用另一种语言编写这个并信任编译器为我生成最佳的机器代码,但我这样做是为了学习如何自己编写最佳的x86汇编程序.我已经查看了生成的代码gcc -O2,我的猜测是有很大的改进空间,但我不够熟练自己编写最佳的x86汇编程序,所以我在这里寻求帮助.
我正在尝试使用FParsec为F#中的Mathematica语言编写解析器.
我为MiniML编写了一个支持语法f x y = (f(x))(y)的函数应用程序具有高优先级.现在我需要使用相同的语法来表示f*x*y,因此具有与multiply相同的优先级.特别是,x y + 2 = x*y + 2而x y ^ 2 = x * y^2.
如何实现这一目标?
复制不可变数据是良性的,但会浪费空间。反向操作共享相等的不可变数据结构,可用于减少内存需求并提供恒定的时间相等性,完美的哈希和字典查找(例如,用于记忆)。可以使用散列精简等技术实现最大共享,并获得唯一表示的数据结构。一个相关的概念是与历史记录无关的数据结构,但其重点是安全性。
我最近在研究此基准测试时注意到,采用唯一表示很容易,并且显着提高了内存消耗和性能。具体地说,通过将符号表达式作为表中给出其组成子表达式的整数索引来引用,并在遇到前所未有的表达式时分配下一个连续整数。此外,当用低级语言(例如C和C ++)解决此类问题时,这种表示形式可以说比传统的(非共享)功能更加自然。众所周知,当使用散列约束为数据结构提供唯一表示时,符号程序,逻辑程序和动态程序(例如OCaml的Boyer基准)的性能要好得多,因此此结果并不令人惊讶或新颖。
但是,使用来自传统语言的哈希精简很麻烦,这引出了一个问题:是否有任何编程语言都会为其原始数据结构自动使用唯一表示形式?
例如,考虑一个具有整数,变量,元组和联合的类似微型ML的类型系统。使用我上面介绍的技术很容易对任何类型的值的构造进行散列处理,因此将最大程度地共享所有结构相同的数据。是否有任何编程语言可以做到这一点?如果没有,是否有停止表演的理由?
一些背景阅读: