Java比C快2倍(作为C ++的子集) [英] Java is 2+ times faster than C (as a subset of C++)

查看:97
本文介绍了Java比C快2倍(作为C ++的子集)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码是一个非常低效的算法来做乘法。它被写作测试目的。我相信我已经编写了相同的代码,但是用不同的语言。

The code below is a very inefficient algorithm to do multiplication. It was written as test purpose. I believe I have written the same code but in different languages.

下面是运行代码的结果。

Right below is the result of running the code.

OS: Windows 7
language: C (as a subset of C++)

compiler: Visual C++
optimization option: /Ox /Oi /Ot /Oy /GL
running time (seconds): 40 +/- 1

compiler: MinGW/gcc
optimization option: -O3 march=native
running time (seconds): 81 +/- 1

compiler: MinGW/g++
optimization option: -O3 march=native
running time (seconds): 82 +/- 1

language: Java

compiler: Oracle JDK
VM: Oracle JVM
running time (seconds): 18 +/- 1



我相信我在我的C代码中做了一些糟糕的事情,编译器完全优化不能以任何方式优化出。如果有什么大问题,请让我知道。我计划一个项目,有一部分涉及大量的计算。我决定在C中编写这个核心计算部分,但是用这种结果,我可能更愿意用Java写一切;它更多更容易,甚至更快?我仍然相信C,所以如果有我的代码中的任何问题,请让我知道。我想要的是,Java版本应该是1.5倍或更慢,但它以某种方式优于C。

I believe I have done something awful in my C code that the compiler with full optimization cannot in whatever way optimize out. If there are any big problem please let me know. I am planning a project that has a part dealing with large amount of computation. I decided to write this core computation part in C, but with this kind of result I may rather write everything in Java; it is lot more easier and even faster? I still believe in C, so if there are any problem in my code please let me know. What I expected was that the Java version should be 1.5 times or more slower, but it somehow outperforms C.

Test.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

typedef signed char byte;

typedef struct _Array
{
    byte *data;
    int len;
}
Array;

void new_Array(Array *a, int len)
{
    a->data = (byte *)malloc(len * sizeof(byte));
    a->len = len;
}

void del_Array(Array *a)
{
    free(a->data);
}

typedef struct _BUI
{
    Array num;
    int len;
}
BUI[1];

void new_BUI(BUI b, const char *s)
{
    int len = strlen(s);
    b->len = len;
    new_Array(&b->num, len);
    for (int i = 0; i < len; ++i)
    {
        b->num.data[i] = s[len - i - 1] - '0';
    }
}

void del_BUI(BUI b)
{
    del_Array(&b->num);
}

int BUI_cmp(const BUI a, const BUI b)
{
    if (a->len > b->len)
    {
        return 1;
    }
    if (a->len < b->len)
    {
        return -1;
    }
    for (int i = a->len - 1; i >= 0; --i)
    {
        if (a->num.data[i] > b->num.data[i])
        {
            return 1;
        }
        if (a->num.data[i] < b->num.data[i])
        {
            return -1;
        }
    }
    return 0;
}

#define MAX(A, B) (A > B ? A : B)

void BUI_add(BUI r, const BUI a, const BUI b)
{
    Array c;
    new_Array(&c, MAX(a->len, b->len) + 1);
    memset(c.data, 0, c.len);
    memcpy(c.data, a->num.data, a->len);
    for (int i = 0; i < b->len; ++i)
    {
        c.data[i] += b->num.data[i];
    }
    for (int i = 0; i < c.len - 1; ++i)
    {
        if (c.data[i] >= 10)
        {
            c.data[i + 1] += c.data[i] / 10;
            c.data[i] %= 10;
        }
    }
    del_Array(&r->num);
    r->num = c;
    r->len = c.len;
    for (int i = r->num.len - 1; r->num.data[i--] == 0; --r->len);
}

void BUI_mul(BUI r, const BUI a, const BUI b)
{
    BUI c;
    new_BUI(c, "0");
    {
        BUI one;
        new_BUI(one, "1");
        BUI i;
        new_BUI(i, "0");
        for (; BUI_cmp(i, a) < 0; BUI_add(i, i, one))
        {
            BUI_add(c, c, b);
        }
        del_BUI(one);
        del_BUI(i);
    }
    del_Array(&r->num);
    r->num = c->num;
    r->len = c->len;
}

void BUI_print(BUI b)
{
    for (int i = b->len - 1; i >= 0; --i)
    {
        putchar(b->num.data[i] + '0');
    }
}

int main(void)
{
    BUI a;
    new_BUI(a, "123456789");
    BUI b;
    new_BUI(b, "987654321");
    BUI_print(a);
    fputs(" x ", stdout);
    BUI_print(b);
    fputs(" = ", stdout);
    time_t start_time = clock();
    BUI_mul(a, a, b);
    time_t end_time = clock();
    BUI_print(a);
    del_BUI(a);
    del_BUI(b);
    printf("\nelapsed time: %.3f\n", (double)(end_time - start_time) / CLOCKS_PER_SEC);
    printf("%d %d\n", a->num.len, a->len);
    return 0;
}

Test.java
$ b

Test.java

import java.util.*;

class BUI
{
    byte[] num;
    int len;

    BUI(String s)
    {
        len = s.length();
        num = new byte[len];
        for (int i = 0; i < len; ++i)
        {
            num[i] = (byte)Character.getNumericValue(s.charAt(len - i - 1));
        }
    }

    int cmp(BUI b)
    {
        if (len > b.len)
        {
            return 1;
        }
        if (len < b.len)
        {
            return -1;
        }
        for (int i = len - 1; i >= 0; --i)
        {
            if (num[i] > b.num[i])
            {
                return 1;
            }
            if (num[i] < b.num[i])
            {
                return -1;
            }
        }
        return 0;
    }

    void add(BUI a, BUI b)
    {
        byte[] c = new byte[Math.max(a.len, b.len) + 1];
        Arrays.fill(c, (byte)0);
        System.arraycopy(a.num, 0, c, 0, a.num.length);
        for (int i = 0; i < b.len; ++i)
        {
            c[i] += b.num[i];
        }
        for (int i = 0; i < c.length - 1; ++i)
        {
            if (c[i] >= 10)
            {
                c[i + 1] += c[i] / 10;
                c[i] %= 10;
            }
        }
        num = c;
        len = c.length;
        for (int i = num.length - 1; num[i--] == 0; --len);
    }

    void mul(BUI a, BUI b)
    {
        BUI c = new BUI("0");
        {
            BUI one = new BUI("1");
            BUI i = new BUI("0");
            for (; i.cmp(a) < 0; i.add(i, one))
            {
                c.add(c, b);
            }
        }
        num = c.num;
        len = c.len;
    }

    void print()
    {
        for (int i = len - 1; i >= 0; --i)
        {
            System.out.print(num[i]);
        }
    }
}


public class Test
{
    public static void main(String[] args)
    {
        BUI a = new BUI("123456789");
        BUI b = new BUI("987654321");
        a.print();
        System.out.print(" x ");
        b.print();
        System.out.print(" = ");
        long start_time = System.currentTimeMillis();
        a.mul(a, b);
        long end_time = System.currentTimeMillis();
        a.print();
        System.out.printf("\nelapsed time: %.3f\n", (end_time - start_time) / 1000.0);
    }
}


推荐答案


language:C(作为C ++的子集)。

"language: C (as a subset of C++)".

只是

C不是C ++的子集。他们有共同的语法(大部分C),但大多数运行时检查是不同的(取决于编译器),代码的解释方式是不同的(在少数情况下),大多数代码为C编写的是非常差的C ++。

C is not a subset of C++. They have common syntax (most of C) but most runtime checks are different (depends on compiler), the way the code is interpreted is different (in a few cases) and most code written for C makes for really poor C++.

C ++有很多设施,可以加快你的算法实现(不确定多少,但如果你正确测量,你一定会看到的变化)。

C++ has quite a few facilities that would speed your algorithm implementation (not sure by how much, but if you measure correctly, you will definitely see the changes).

对于一个简单的例子,对字符数组使用std :: string。

For a simple example, use std::string for character arrays.


项目中有一部分涉及大量的计算。我决定在C中编写这个核心计算部分,但是用这种结果我可以用Java写一切;

I am planning a project that has a part dealing with large amount of computation. I decided to write this core computation part in C, but with this kind of result I may rather write everything in Java;

它(即,如果它更容易为你写在Java中)。你可以在C中获得更好的性能,就像你可以在Java中获得更好的性能。

Go for it (that is, write it in Java if it is simpler to you). You could get better performance in C, just like you could get better performance in Java. It is up to you to decide how much time and effort you put into optimizing your algorithms and code.

计算速度不会来自使用优化选项运行编译器 - 很好,它的确实际上,但是相对于来自算法优化的速度相对较小。你可以通过在你熟悉的开发工具链中进行优化,然后绊倒你不熟悉的语言,获得更多的速度。

Computation speed will not come from running the compiler with optimization options - well, it does actually, but that's relatively small compared to speed coming from algorithmic optimizations. You could get more speed though by optimizing in a development tool chain you are familiar with, then stumbling through a language you are not familiar with.


它更多更容易,甚至更快?我仍然相信C,所以如果有我的代码中的任何问题,请让我知道。我的预期是,Java版本应该是1.5倍或更慢,但它以某种方式优于C。

it is lot more easier and even faster? I still believe in C, so if there are any problem in my code please let me know. What I expected was that the Java version should be 1.5 times or more slower, but it somehow outperforms C.

您的逻辑是有缺陷的。

Your logic is flawed.

您所写的比较并不代表C和Java之间的速度差异(以及C ++和Java之间的速度差异)。

The comparison you wrote is not representative for speed differences between C and Java (and even less between C++ and Java) in any way. It is representative for comparing these two implementations, compiled in different languages, not the languages themselves.

换句话说,比较这样的两个应用程序,即使它们看起来是等效的,不比较语言(或编译器)的速度。它只是比较两个不同的程序,运行非常不同的版本的相同的算法。这是一种特殊情况。

In other words, comparing two applications like this, even when they seem equivalent, doesn't compare the languages (or compilers) for speed. It simply compares two different programs, running very different versions of the same algorithm. It is a particular case.

您的C代码已编译。它将在不同的硬件(例如两个处理器与四个处理器)上具有不同的性能特性。

Your C code is compiled. It will have different performance characteristics on different hardware (for example two processors versus four processors).

您的java代码是字节编译的。它将在大多数Java虚拟机运行之前进行优化,以最佳地匹配您的代码将在其上运行的平台。

Your java code is byte-compiled. It will be optimized before running by most Java VMs, to best match the platform your code will run on.

最后,您可能更积极地在C或C ++比在Java中,如果你需要编写真正的性能关键代码,比你可能获得不能由Java匹配的C或C ++代码,因为它将比运行Java VM本身所需的速度阈值更快。

In the end, you could probably optimize more aggressively in C or C++ than in Java, and if you need to write truly performance-critical code, than you can possibly obtain C or C++ code that cannot be matched by Java, because it would be faster than the speed threshold required to run the Java VM itself.

这种优化虽然在特定情况下需要大量的时间和精力进行分析和优化,但大多数应用程序域不需要它。如果你不知道你是否需要这样的性能水平,你可能不会。

Such optimization though would take lots of time and effort in profiling and optimizing in particular cases, and most application domains do not need it. If you do not know if you need that level of performance, you probably don't.

这篇关于Java比C快2倍(作为C ++的子集)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆