Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java CAS操作的执行速度比同等的C语言快,为什么? 这里有Java和C代码,它们试图使用CAS执行原子增量操作 将长变量从0增加到500000000 C:所用时间:7300毫秒 爪哇:所用时间:2083毫秒 有人能再检查一下这些结果吗?因为我简直不敢相信他们 谢谢_Java_C_Concurrency_Compare And Swap - Fatal编程技术网

Java CAS操作的执行速度比同等的C语言快,为什么? 这里有Java和C代码,它们试图使用CAS执行原子增量操作 将长变量从0增加到500000000 C:所用时间:7300毫秒 爪哇:所用时间:2083毫秒 有人能再检查一下这些结果吗?因为我简直不敢相信他们 谢谢

Java CAS操作的执行速度比同等的C语言快,为什么? 这里有Java和C代码,它们试图使用CAS执行原子增量操作 将长变量从0增加到500000000 C:所用时间:7300毫秒 爪哇:所用时间:2083毫秒 有人能再检查一下这些结果吗?因为我简直不敢相信他们 谢谢,java,c,concurrency,compare-and-swap,Java,C,Concurrency,Compare And Swap,Java代码: import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; public class SmallerCASTest { public static void main(String[] args){ final long MAX = 500l * 1000l * 1000l; final AtomicLong counter =

Java代码:

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

public class SmallerCASTest {

    public static void main(String[] args){
        final long MAX = 500l * 1000l * 1000l;
        final AtomicLong counter = new AtomicLong(0);

        long start = System.nanoTime();
        while (true) {
            if (counter.incrementAndGet() >= MAX) {
                break;
            }
        }

        long casTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
        System.out.println("Time Taken=" + casTime + "ms");
    }

}
C代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NITER 500000000


int main (){
   long val = 0;     
   clock_t starttime = clock ();
    while (val < NITER){
      while (1){
        long current = val;
        long next = current+1;
        if ( __sync_bool_compare_and_swap (&val, current, next))
            break;
      }
     } 
   clock_t castime = (clock()-starttime)/ (CLOCKS_PER_SEC / 1000);
   printf ("Time taken : %d ",castime);
}
其他详情:

System : Linux XXXXXXXXX #1 SMP Thu Mar 22 08:00:08 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux

gcc --version:
 gcc (GCC) 4.4.6 20110731 (Red Hat 4.4.6-3)

java -version: 
java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b04)
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01, mixed mode)

EDIT事实上,正如您所指出的,java似乎使用CAS操作实现了incrementAndGet

我的测试似乎表明C和Java版本的性能大致相当(这是有道理的,因为耗时的部分是原子级的,而不是Java或C编译器设法对其余部分进行的任何优化)

因此,在我的机器(Xeon X3450)上,java版本大约需要4700毫秒,C版本大约需要4600毫秒,C版本使用u_sync_add_和_fetch()~3800毫秒(这意味着可以改进java,而不是在CAS上实现所有原子操作)

java版本是


java version "1.6.0_24"
OpenJDK Runtime Environment (IcedTea6 1.11.4) (6b24-1.11.4-1ubuntu0.10.04.1)
OpenJDK 64-Bit Server VM (build 20.0-b12, mixed mode)
GCC是4.4.3,x86_64

操作系统是Ubuntu 10.04 x86_64


因此,我只能得出结论,在你的测试中,有些东西似乎可疑。

你在比较苹果和桔子,我相信你是这么想的。
java
版本是一个真正的CAS,失败时重试,
C
版本使用的是我在
java
a
synchronized
表单中调用的内容

有关更多详细信息,请参阅

请注意这个问题,以支持这样的叙述:调用此函数时会创建一个完整的内存屏障,即,在java术语中,这是一个
同步的
调用

试着以同样的方式使用
AtomicLong
使用它的java等价物,即在函数上旋转,直到值更改为您想要的值

添加:

<>我找不到一个与Java < AtomicLong >代码>相同的C++等价物,但这并不意味着没有java。本质上,
AtomicLong
可以由任何线程在任何时候更改,并且只有一个线程成功。但是,更改是一致的,即更改是一个或另一个线程更改的结果,而不是这两个线程的组合。如果线程A尝试将值更改为0xffff0000(或等效的64位数字),而线程B尝试更改为0x0000ffff(同上),则结果将是两个值中的一个,更具体地说,它将不是0x00000000或0xFFFFFF(当然,除非涉及第三个线程)


本质上,
AtomicLong
没有任何同步

因为Java很棒

java版本的每个循环需要4ns。差不多是这样。无争用CAS实际上是CPU本地操作,它应该非常快。(编辑:可能不是4ns快!)

Java通过积极的运行时优化实现了这一速度,代码是内联的,只需几条机器指令,也就是说,在汇编中输入代码的速度是最快的


如果gcc版本不能内联函数调用,那么每个循环都会有很大的开销。

在测量之前,通过预热JVM,可以在Java中获得更好的结果。可以想象,由于代码是单线程的,JVM优化了同步的需要,有效地增加了一个长变量。它甚至可能确定递增的变量从未使用过,并优化整个循环。。。等等……有人能重现java示例的数字吗?在我的机器上,java示例在我的机器(Xeon X3450)上需要7500ms,java版本需要约4700 ms,C版本需要约4600 ms,C版本使用uuu sync_uadd_uand u fetch()~3800 ms。@janneb,你是否在使用mac?什么操作系统,java和c的版本,也可以使用openJDK或sunJDK。我发现在mac上,两个程序的性能相同。同样,OpenJDK的结果也不同。我对sunJdk特别感兴趣,在linux上它往往比C更出色。@Jigar:请看下面我的更新答案。不这样认为,请查看incrementAndGet的来源。不,还没有任何可疑之处。正如您所说,您正在使用OpenJDK,请尝试sunJDK,然后我们可以讨论我的测试是否可疑。不管怎样,感谢您运行这些测试,我现在将删除我的否决票。@Jigar:好吧,我确实认为如果sunjdk能够以比C或openjdk快3倍的速度“锁定cmpxchg”是很可疑的。看到生成的asm会很有趣(在java中可能吗?)。据我所知,您是否试图说_sync**正在创建一个内存屏障,而编译器无法优化其周围的代码,因此速度会减慢?如果是这样的话,在GCC中是否有一些替代方案,我可以使用它们获得与java相同的结果?(你提供的)SypReaReaSyand交换链接指向了一些“XLC for AIX,V121”编译器,我认为我不能使用。)不是C++大师——抱歉。我不知道有没有类似的,也许其他人会建议。。。。但这可能是一个好的开始。看起来仅仅使用
volatile
可能是一种有效的等效方法。事实上,不要去那里,只使用<代码>易失性>代码> @ OrdCurgGuon“只使用一个易失性”——不,不适用于C或C++。java VS C++或C++中的语义/保证是不同的。不要去那里:“OrdCurgGueon C++(和C)使用顺序一致性执行。e、 g.编译器和/或硬件可以自由地对指令进行重新排序,只要指令“好像”没有重新排序。默认情况下,对内存的访问和读/写是不受限制的,可以重新排序、中断等。原子操作的具体实现因体系结构而异。在最新的C++和C内存模型下的原子性实际上是保证内存区域上的原子操作不能中断(例如上下文切换)或该区域可能不会同时从另一个线程访问。

java version "1.6.0_24"
OpenJDK Runtime Environment (IcedTea6 1.11.4) (6b24-1.11.4-1ubuntu0.10.04.1)
OpenJDK 64-Bit Server VM (build 20.0-b12, mixed mode)