|
[ Dejan Lozanovic @ 25.11.2007. 13:23 ] @
| Silom prilika moram jedan projekt da uradim u .NJET platformi pa uzurbano ucim C#, uzeo na vistu x64 instaliram Visual Studio Express 2008 koji je sa sobom doneo i .NJET 3.5, i kako naravno krecete da se igrate uceci novi programski jezik prosto vas pomami da napravite mali mini performace test uzmem recimo mnozenje matrica velicine 100x100 i pomnozim dve matrice 10 000 puta. I od rezultata imam sta da vidim
pokrenem C# program i njemu je trebalo 56 sekundi da sve to izracuna,
Mono 3 minuta i 35 sekundi
Javi treba 21-26 sekundi ( u zavisnosti da li pokrenem kao client ili server ili pod Vistom ili linux-om),
gcc (4.1.2) bez optimizacije 1 minut i 50 sec,
gcc -O2 17 sec, sve to pokrecem na AMD 5000+.
Pa se pitam u cemu je fazon da .NJET to tako sporo radi , da nema mozda neki turbo switch posto java vise nego duplo brze mnozi matrice.
Code:
using System;
namespace Proba
{
class Program
{
static private int SIZE = 100;
static void Main(string[] args)
{
DateTime d1 = DateTime.Now;
for (int i = 0; i < 10; i++)
{
test();
}
DateTime d2 = DateTime.Now;
TimeSpan t1 = d2 - d1;
System.Console.WriteLine(t1.ToString());
}
public static void test()
{
int n = 1000;
int [,]m1 = mkmatrix(SIZE, SIZE);
int [,]m2 = mkmatrix(SIZE, SIZE);
int [,]mm = new int[SIZE,SIZE];
for (int i = 0; i < n; i++) {
mmult(SIZE, SIZE, m1, m2, mm);
}
}
public static int[,] mkmatrix(int rows, int cols) {
int count = 1;
int[,] m = new int[rows, cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m[i,j] = count++;
}
}
return (m);
}
public static void mmult(int rows, int cols, int[,] m1, int[,] m2,
int[,] m3)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
int val = 0;
for (int k = 0; k < cols; k++)
{
val += m1[i,k] * m2[k,j];
}
m3[i,j] = val;
}
}
}
}
}
Code:
public class MatMult {
static int SIZE = 100;
public static void main(String args[]) {
long t1 = System.currentTimeMillis();
for (int i = 1; i < 10; i++)
test();
System.out.println(System.currentTimeMillis() - t1);
}
public static void test() {
int n = 1000;
int m1[][] = mkmatrix(SIZE, SIZE);
int m2[][] = mkmatrix(SIZE, SIZE);
int mm[][] = new int[SIZE][SIZE];
for (int i = 0; i < n; i++) {
mmult(SIZE, SIZE, m1, m2, mm);
}
}
public static int[][] mkmatrix(int rows, int cols) {
int count = 1;
int m[][] = new int[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m[i][j] = count++;
}
}
return (m);
}
public static void mmult(int rows, int cols, int[][] m1, int[][] m2,
int[][] m3) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int val = 0;
for (int k = 0; k < cols; k++) {
val += m1[i][k] * m2[k][j];
}
m3[i][j] = val;
}
}
}
}
|
[ hipik @ 25.11.2007. 13:46 ] @
Dejane puno srece ;)
Hipik ZM
[ tosa @ 25.11.2007. 14:01 ] @
Fazon je u loše napisanom programu, vidi se da još uvek učiš C# :)
Pored dinamičkih alokacija koje, verujem, nemaš u C++ programu, na zanimljiv način prosleđuješ parametre!
[ Dejan Lozanovic @ 25.11.2007. 14:14 ] @
Citat: tosa: Fazon je u loše napisanom programu, vidi se da još uvek učiš C# :)
Pored dinamičkih alokacija koje, verujem, nemaš u C++ programu, na zanimljiv način prosleđuješ parametre!
Ovaj kod je uzet sa jednog od java vs C++ benchamarka, tacnije javin source je samo sintaksno prebacen na C# posto se multidimenzioni nizovi drugacije sintaksno oznacavaju.
Code:
// -*- mode: c++ -*-
// $Id: matrix.g++,v 1.3 2001/06/20 03:20:02 doug Exp $
// http://www.bagley.org/~doug/shootout/
#include <iostream>
#include <stdlib.h>
using namespace std;
#define SIZE 100
int **mkmatrix(int rows, int cols) {
int i, j, count = 1;
int **m = (int **) malloc(rows * sizeof(int *));
for (i=0; i<rows; i++) {
m[i] = (int *) malloc(cols * sizeof(int));
for (j=0; j<cols; j++) {
m[i][j] = count++;
}
}
return(m);
}
void zeromatrix(int rows, int cols, int **m) {
int i, j;
for (i=0; i<rows; i++)
for (j=0; j<cols; j++)
m[i][j] = 0;
}
void freematrix(int rows, int **m) {
while (--rows > -1) { free(m[rows]); }
free(m);
}
int **mmult(int rows, int cols, int **m1, int **m2, int **m3) {
int i, j, k, val;
for (i=0; i<rows; i++) {
for (j=0; j<cols; j++) {
val = 0;
for (k=0; k<cols; k++) {
val += m1[i][k] * m2[k][j];
}
m3[i][j] = val;
}
}
return(m3);
}
int main(int argc, char *argv[]) {
int i, n = 10000;
int **m1 = mkmatrix(SIZE, SIZE);
int **m2 = mkmatrix(SIZE, SIZE);
int **mm = mkmatrix(SIZE, SIZE);
for (i=0; i<n; i++) {
mm = mmult(SIZE, SIZE, m1, m2, mm);
}
freematrix(SIZE, m1);
freematrix(SIZE, m2);
freematrix(SIZE, mm);
return(0);
}
[ VRider @ 25.11.2007. 14:49 ] @
@tosa: ako mislis da treba drugacije i da rezultat moze biti znatno bolji, daj kod, pa ce Deki da testira...
[ negyxo @ 25.11.2007. 16:00 ] @
Code:
using System;
using System.Collections.Generic;
using System.Text;
namespace Matrix2
{
using System;
namespace Proba
{
class Program
{
static private int SIZE = 100;
static void Main(string[] args) {
DateTime d1 = DateTime.Now;
for (int i = 0; i < 10; i++) {
test();
}
DateTime d2 = DateTime.Now;
TimeSpan t1 = d2 - d1;
System.Console.WriteLine(t1.ToString());
System.Console.ReadLine();
}
public static void test() {
int n = 1000;
int[][] m1 = mkmatrix(SIZE, SIZE);
int[][] m2 = mkmatrix(SIZE, SIZE);
int[][] mm = new int[SIZE][];
for (int i = 0; i < SIZE; i++) {
mm[i] = new int[SIZE];
}
for (int i = 0; i < n; i++) {
mmult(SIZE, SIZE, m1, m2, mm);
}
}
public static int[][] mkmatrix(int rows, int cols) {
int count = 1;
int[][] m = new int[rows][];
for (int i = 0; i < rows; i++) {
m[i] = new int[cols];
for (int j = 0; j < cols; j++) {
m[i][j] = count++;
}
}
return (m);
}
public static void mmult(int rows, int cols, int[][] m1, int[][] m2, int[][] m3) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int val = 0;
for (int k = 0; k < cols; k++) {
val += m1[i][k] * m2[k][j];
}
m3[i][j] = val;
}
}
}
}
}
}
Ovde je problem sto code, iako na prvi pogled identican, to nije. Razlika je u alociranju niza. U java delu, to su jagged nizovi dok u C# je standardni rectangular niz (dvodimenzionalni niz, multidiminezioni... wathever  )
[ tosa @ 25.11.2007. 16:00 ] @
@VRider
A zbog čega? Draže mi je da se muči kad pre istraživanja/učenja prosipa optužbe.
Odakle je kod preuzet je nebitno, svakakvi "stručnjaci" po internetu prosipaju znanja...
Nije teško napraviti spor kod u C#, to stoji, ali isto tako može biti veoma brz, blizu C++-a
(sa pretpostavkom da je u pitanju samo haj level kod).
Sami inicijalni rezultati su smešni, C++ po toj logici ispada sporiji od Jave :D
Garantujem da je 90+% vremena C++ proveo u malloc funkciji - dakle loš dizajn (a još malloc u C++-u :)).
[ VRider @ 25.11.2007. 16:16 ] @
Postoji velika razlika izmedju kriticara i kritizera. Ako samo kazes "kod ne valja" onda ti spadas u ovu drugu grupu.
Mozda ti smatras da nema potrebe da bilo kome bilo sta dokazujes - onda si pogresio forum - Advocacy i sluzi da drugima nesto dokazujes, cak i ako to nema veze sa istinom. 
[ tosa @ 25.11.2007. 16:42 ] @
Citat: tosa: Sami inicijalni rezultati su smešni, C++ po toj logici ispada sporiji od Jave :D
Garantujem da je 90+% vremena C++ proveo u malloc funkciji - dakle loš dizajn (a još malloc u C++-u :)).
[ Dejan Lozanovic @ 25.11.2007. 17:08 ] @
Citat: Ovde je problem sto code, iako na prvi pogled identican, to nije. Razlika je u alociranju niza. U java delu, to su jagged nizovi dok u C# je standardni rectangular niz (dvodimenzionalni niz, multidiminezioni... wathever  )
Hvala
00:00:38.3260000 , ali to je opet sporije od 21 sekunde koju vadim sa javom
Citat: Sami inicijalni rezultati su smešni, C++ po toj logici ispada sporiji od Jave 
Garantujem da je 90+% vremena C++ proveo u malloc funkciji - dakle loš dizajn (a još malloc u C++-u  ).
Pa da mislim svi se slazemo da algoritam sam kao takav nije najoptimizovaniji, ali sva tri jezika koriste isti algoritam. Tj mislim da masis poentu ne gledamo apsolutno najidealniji algoritam, gledamo kojom brzinom sva tri jezika izvrsavaju dati algoritam, i kako stvari stoje na ovom primeru Zlatna medalja C++, Srebrna Java, Bronzana C# 
[ Dejan Lozanovic @ 25.11.2007. 17:27 ] @
Citat: Dejan Lozanovic:
Hvala
00:00:38.3260000 , ali to je opet sporije od 21 sekunde koju vadim sa javom
Eh da nije me mrzelo da skinem malo pre java 7 ea, mislim da su rezultati mozda malo vise porazavajuci. u odnosu na .NET
Code:
c:\workspace-test\Test\src>java MatMult
15452
c:\workspace-test\Test\src>java MatMult
15476
A sada ako kojim slucajem zelis da izvucemo suvu drenovinu iz algoritma nije problem, mozemo da optimizujemo algoritam pa da pokrenemo testove.
[ tosa @ 25.11.2007. 18:13 ] @
Citat: Dejan Lozanovic: Pa da mislim svi se slazemo da algoritam sam kao takav nije najoptimizovaniji, ali sva tri jezika koriste isti algoritam. Tj mislim da masis poentu ne gledamo apsolutno najidealniji algoritam, gledamo kojom brzinom sva tri jezika izvrsavaju dati algoritam, i kako stvari stoje na ovom primeru Zlatna medalja C++, Srebrna Java, Bronzana C# :D
Stvarno bi trebalo malo bolje da izučiš kako rade garbidž kolektori za javu i za C#,
koliko je alokacija memorije skupa operacija i tako dalje, da bi shvatio da je poređenje
koje praviš potpuno pogrešno. Algoritam je nebitan, bitna je implementacija što je
na ovom primeru više nego očigledno. Može tako i P4 da bude sporiji od 286 ;)
Vidim pričaš sada kako C++ nosi zlatnu medalju, kako to da u tvojim prvim testovima
C++ program je bio sporiji java verzije više od dva puta? Kao što rekoh, objašnjenje
se može potražiti samo u autoru programa... Potraži poređenja između C#-a i C++-a,
kad već surfuješ umesto da meriš.
Java, i implementacije njene virtuelne mašine, je na granici da bude jedini nedeterministički jezik ;)
[ Dejan Lozanovic @ 25.11.2007. 18:19 ] @
Citat: tosa: Stvarno bi trebalo malo bolje da izučiš kako rade garbidž kolektori za javu i za C#,
koliko je alokacija memorije skupa operacija i tako dalje, da bi shvatio da je poređenje
koje praviš potpuno pogrešno. Algoritam je nebitan, bitna je implementacija što je
na ovom primeru više nego očigledno. Može tako i P4 da bude sporiji od 286 ;)
Vidim pričaš sada kako C++ nosi zlatnu medalju, kako to da u tvojim prvim testovima
C++ program je bio sporiji java verzije više od dva puta? Kao što rekoh, objašnjenje
se može potražiti samo u autoru programa... Potraži poređenja između C#-a i C++-a,
kad već surfuješ umesto da meriš.
Huh, ajde molim te pogledaj prvi post, gde sam rekao g++ Bez optimizacije 1 minut 50 sekundi i g++ sa -O2 17 sekundi kao sto vidis dva rezultata sam dao za gnuov C++ kompajler.
I drugo koliko god da je losa sama implementacija algoritma u globalu, losa je na sva tri jezika, nije java postedjenija u odnosu na C# ili C++ primer.
Citat:
Java, i implementacije njene virtuelne mašine, je na granici da bude jedini nedeterministički jezik ;)
Ok drzimo se onda Sun-ovog hotspot-a to je implementacija, ako ti je lakse za merenje :D
[ anon315 @ 25.11.2007. 19:10 ] @
toso, najbolje ces pokazati ako das kod, pa da Dejan izmeri. Nema potrebe da pricamo price, kod i test performansi ce da kaze sve ;) Poenta je da imamo konstruktivnu raspravu..
[ caboom @ 25.11.2007. 19:38 ] @
imho - konstruktivna rasprava nad great language shootout primerima je uglavnom besmislena.
over&out
[ Dejan Lozanovic @ 25.11.2007. 19:38 ] @
Citat: tosa: Garantujem da je 90+% vremena C++ proveo u malloc funkciji - dakle loš dizajn (a još malloc u C++-u :)).
Hmm, a jel mozemo da se malo zaigramo sa teorijom :),
kada pozoves malloc, kako se alocira memorija mallocom, da li za svaki poziv malloc funkcije ti trazis od operativnog sistema za novi segment memorije ili se nesto drugo desava (hint: jesi li cuo nekada za brk() ili sbrk() i kakve oni imaju veze sa mallocom ?).
Drugo koliki je mimum bajtova koji ce malloc da ti vrati ?
Trece koja je razlika izmedju malloc-a/new sa C++ i GC na javi i C# ako konstanto samo alociras memoriju bez da je dealociras ?
Cetvrto da li si ikada "frizirao" C++ pa pravio ovakav kod
Code:
A *v1 = (A*) malloc(sizeof(A));
Sta se sa ovime desava ?
Peto zasto je malloc brzi nego new ?
I na kraju ubacio sam merenje u C++ samo izmedju for petlje gde pravimo mnozenje izmedju dve matrice, evo ti code
Code:
// -*- mode: c++ -*-
// $Id: matrix.g++,v 1.3 2001/06/20 03:20:02 doug Exp $
// http://www.bagley.org/~doug/shootout/
#include <stdlib.h>
#include <sys/time.h>
#include <iostream>
#define SIZE 100
using namespace std;
int **mkmatrix(int rows, int cols) {
int i, j, count = 1;
int **m = (int **) malloc(rows * sizeof(int *));
for (i=0; i<rows; i++) {
m[i] = (int *) malloc(cols * sizeof(int));
for (j=0; j<cols; j++) {
m[i][j] = count++;
}
}
return(m);
}
void zeromatrix(int rows, int cols, int **m) {
int i, j;
for (i=0; i<rows; i++)
for (j=0; j<cols; j++)
m[i][j] = 0;
}
void freematrix(int rows, int **m) {
while (--rows > -1) { free(m[rows]); }
free(m);
}
int **mmult(int rows, int cols, int **m1, int **m2, int **m3) {
int i, j, k, val;
for (i=0; i<rows; i++) {
for (j=0; j<cols; j++) {
val = 0;
for (k=0; k<cols; k++) {
val += m1[i][k] * m2[k][j];
}
m3[i][j] = val;
}
}
return(m3);
}
int main(int argc, char *argv[]) {
int i, n = 10000;
int **m1 = mkmatrix(SIZE, SIZE);
int **m2 = mkmatrix(SIZE, SIZE);
int **mm = mkmatrix(SIZE, SIZE);
struct timeval t1,t2;
gettimeofday(&t1,NULL);
for (i=0; i<n; i++) {
mm = mmult(SIZE, SIZE, m1, m2, mm);
}
gettimeofday(&t2,NULL);
cout << "provedeno vreme mnozeci matrice: " << ((t2.tv_sec*1000000+t2.tv_usec)-(t1.tv_sec*1000000+t1.tv_usec))/1000;
freematrix(SIZE, m1);
freematrix(SIZE, m2);
freematrix(SIZE, mm);
return(0);
}
A evo sta kaze izlaz
Code:
[dejan@DEJAN]$ time ./a.out
provedeno vreme mnozeci matrice: 17614
real 0m17.619s
user 0m17.609s
sys 0m0.006s
Primeti ono sys to je vreme provedeno u kernel-u(zahtevi za alokacijom memorije) pa sada zakljuci koliko je vremena proveo u kom delu programa.
[ caboom @ 25.11.2007. 19:45 ] @
ovaj... prilicno sam siguran da je tosha upoznat sa ovim, verovatno i dosta bolje od nas, verovatno i sa efikasnijim metodima alokacije memorije bez blokiranja na heap-u - to mu je posao. daj bre dejane gde si iskopao brk/sbrk... you're so 90'es :)
[ NastyBoy @ 25.11.2007. 20:13 ] @
Citat: imho - konstruktivna rasprava nad great language shootout primerima je uglavnom besmislena.
^ What he said.
Ali...
Citat: Cetvrto da li si ikada "frizirao" C++ pa pravio ovakav kod A *v1 = (A*) malloc(sizeof(A));
Gde pod "frizirano" ustvari mislish na "da li si ikada popio otkaz kad si napisao ovakav C++ kod"?
[ tosa @ 26.11.2007. 01:39 ] @
Citat: Dejan Lozanovic: Trece koja je razlika izmedju malloc-a/new sa C++ i GC na javi i C# ako konstanto samo alociras memoriju bez da je dealociras ?
Cetvrto da li si ikada "frizirao" C++ pa pravio ovakav kod
Nemoj da se blamiraš dalje :)
Citat: NastyBoy: Gde pod "frizirano" ustvari mislish na "da li si ikada popio otkaz kad si napisao ovakav C++ kod"?
LOL!
[ VRider @ 26.11.2007. 02:01 ] @
Nemoj ti, Toso, da se blamiras!
[ tosa @ 26.11.2007. 03:57 ] @
Evo ga još jedan... Da te nije lično pogodilo? :)
Pošto već pozivaš na argumentaciju, ajde ti lepo sad obrazloži moj blam,
ja nisam taj koji je pisao invalidan C++ kod, samo sam mu se smejao.
JAVAšluk je to čisti, ja da ti kažem...
[ VRider @ 26.11.2007. 09:15 ] @
Nije me licno pogodilo.
Zasto bih argumentovao? Draze mi je da se mucis... 
[ Časlav Ilić @ 26.11.2007. 09:32 ] @
Ima li neki poseban razlog zašto se meri množenje 100×100 matrica? Mene bi više interesovalo upoređenje na množenju, recimo, 2053×2053 matrica.
U tom slučaju, što se C-kôda tiče, prepraviti stvaranje matrica tako da se sigurno rezerviše neprekidan blok memorije:
Code: int **mkmatrix(int rows, int cols) {
int i, j, count = 1;
int **m = (int **) malloc(rows * sizeof(int *));
int *d = (int *) malloc(rows * cols * sizeof(int));
for (i=0; i<rows; i++) {
m[i] = d + i * cols;
}
return(m);
}
void freematrix(int rows, int **m) {
free(*m);
free(m);
}
a u jezgru petlji izvrnuti redosled dve unutrašnje radi izbegavanja skokova preko vrsta:
Code: int **mmult(int rows, int cols, int **m1, int **m2, int **m3) {
int i, j, k;
zeromatrix(rows, cols, m3);
for (i=0; i<rows; i++) {
for (k=0; k<cols; k++) {
for (j=0; j<cols; j ++) {
m3[i][j] += m1[i][k] * m2[k][j];
}
}
}
return(m3);
}
[ tosa @ 26.11.2007. 09:45 ] @
Citat: VRider: Nije me licno pogodilo.
Zasto bih argumentovao? Draze mi je da se mucis... :)
Zašto? Zato što se ničim izazvan nalaziš prozvanim, dakle radi sujeta...
Tvoj istomišljenik je izneo par misli u kojima dokazuje da ne zna o čemu priča
i ja sam mu lepo savetovao da se ne blamira, tvoj problem što se to odnosi i
na tebe.
[ Ivan Dimkovic @ 26.11.2007. 10:44 ] @
Elem, kod mene se cela stvar izvrsava za 32 sec (VS 2008, Intel Quad Core na 3 GHz, Vista x64)
Medjutim, iz znatizelje sam promenio redosled pristupa matrici:
Code:
public static void mmult(int rows, int cols, int[,] m1, int[,] m2,
int[,] m3)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
int val = 0;
for (int k = 0; k < cols; k++)
{
val += m1[k,i] * m2[j,k];
}
m3[j,i] = val;
}
}
}
Sada se kod izvrsava za 26 sekundi... kako je matrica kvadratna nema razlike, ali ocigledno ima razlike u nacinu na koji su smestene matrice u C# i njihovom pristupanju u primeru :)
Javu na zalost nemam (niti imam nameru da instaliram ;-) pa da izmerim koliko se to kod mene izvrsava u Javi.
Kao sto rekoh - da je ovde ocigledno problem nacin na koji je alocirana memorija za matrice u C# portu i nacin na koji joj se pristupa u ovom primeru... blagog pojma nemam o C#-u pa ne bih to da komentarisem, ali nesto mi govori da je to moguce izvesti na bolji nacin :-)
@edit - Caslav je napisao kako se to radi u C-u, na tako nesto sam ciljao i u C# ali kako ne poznajem taj jezik bolje da neko strucniji to napise :)
[ zika.pavlovic @ 29.11.2007. 22:29 ] @
[ Ivan Dimkovic @ 29.11.2007. 22:59 ] @
Vazi za MS proizvode i za zemlje gde EULA znaci nesto ;-)
U Nemackoj EULA nema zakonsku bitnost - a Dejan je svoj "benchmark" dobio uz pomoc Mono-a koliko sam shvatio, tako da i nije koristio MS softver ;-)
Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|