|
-
Aug 3rd, 2009, 07:08 PM
#1
[RESOLVED] Make this faster
My friend and I are comparing VB's speed to C++, and so far his is a lot faster (about 10 x's).
Maybe some speed guru could help make this even faster using some APIs I probably don't know about or other techniques? It's basically math.
Anyway, here's my code, followed by his C++ code.
Code:
Option Explicit
Private Const MILLION As Long = 1000001
Private Type Vector
x As Long
y As Long
z As Long
End Type
Private Type LARGE_INTEGER
LowPart As Long
HighPart As Long
End Type
Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As LARGE_INTEGER) As Long
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As LARGE_INTEGER) As Long
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private udtStart As LARGE_INTEGER, udtEnd As LARGE_INTEGER
Private curStart As Currency, curEnd As Currency
Private udtFrequency As LARGE_INTEGER, curFrequency As Currency
Private Sub Vector_Add(ByRef TheVector As Vector, ByVal Factor As Long)
With TheVector
.x = .x + Factor
.y = .y + Factor
.z = .z + Factor
End With
End Sub
Private Sub Vector_Multiply(ByRef TheVector As Vector, ByVal Factor As Long)
With TheVector
.x = .x * Factor
.y = .y * Factor
.z = .z * Factor
End With
End Sub
Private Sub Vector_Divide(ByRef TheVector As Vector, ByVal Factor As Long)
With TheVector
.x = .x / Factor
.y = .y / Factor
.z = .z / Factor
End With
End Sub
Private Function LargeIntToCurrency(ByRef LargeInteger As LARGE_INTEGER) As Currency
CopyMemory LargeIntToCurrency, LargeInteger, LenB(LargeInteger)
LargeIntToCurrency = LargeIntToCurrency * 10000
End Function
Private Sub Form_Load()
If QueryPerformanceFrequency(udtFrequency) = 0 Then
MsgBox "QPC not available on your piece of **** computer!", vbExclamation
Unload Me
End If
curFrequency = LargeIntToCurrency(udtFrequency)
Dim v1 As Vector, v2 As Vector, v3 As Vector
With v1
.x = 1
.y = 2
.z = 3
End With
With v2
.x = 100
.y = 200
.z = 300
End With
With v3
.x = 40
.y = 50
.z = 60
End With
Dim tmp1 As Vector, tmp2 As Vector
Dim tmp3 As Vector, tmp As Vector
tmp = v1
'tmp += 1
Vector_Add tmp, 1
If tmp.x = 2 And tmp.y = 3 And tmp.z = 4 Then
MsgBox "Test1: Ok!", vbInformation
End If
tmp = v2
'tmp *= 2
Vector_Multiply tmp, 2
If tmp.x = 200 And tmp.y = 400 And tmp.z = 600 Then
MsgBox "Test2: Ok!", vbInformation
End If
tmp = v3
Vector_Divide tmp, 10
If tmp.x = 4 And tmp.y = 5 And tmp.z = 6 Then
MsgBox "Test3: Ok!", vbInformation
End If
'* Timed code begins here *
'TIME_BEGIN:
QueryPerformanceCounter udtStart
Dim i As Long
For i = 1 To MILLION
'Vector 1
'CopyMemory tmp, v1, 12
tmp = v1
'Add, multiply, divide
With tmp
.x = .x + i
.y = .y + i
.z = .z + i
.x = .x * i
.y = .y * i
.z = .z * i
.x = .x / i
.y = .y / i
.z = .z / i
End With
'Vector 2
'CopyMemory tmp, v2, 12
tmp = v2
With tmp
.x = .x + i
.y = .y + i
.z = .z + i
.x = .x * i
.y = .y * i
.z = .z * i
.x = .x / i
.y = .y / i
.z = .z / i
End With
'Vector 3
'CopyMemory tmp, v3, 12
tmp = v3
With tmp
.x = .x + i
.y = .y + i
.z = .z + i
.x = .x * i
.y = .y * i
.z = .z * i
.x = .x / i
.y = .y / i
.z = .z / i
End With
Next i
'TIME_END:
QueryPerformanceCounter udtEnd
curStart = LargeIntToCurrency(udtStart)
curEnd = LargeIntToCurrency(udtEnd)
'((end - start) / freq) * 1000)
MsgBox ((curEnd - curStart) / curFrequency) * 1000, vbInformation
End Sub
C++ code:
Code:
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "kernel32")
#define TIME_BEGIN double freq, start, end; \
QueryPerformanceFrequency((LARGE_INTEGER *)&freq); \
QueryPerformanceCounter((LARGE_INTEGER *)&start);
#define TIME_END QueryPerformanceCounter((LARGE_INTEGER *)&end); \
printf("Timer: %f ms\n", ((end - start) / freq) * 1000);
struct vector
{
double x, y, z;
void operator += (long f)
{
x += f;
y += f;
z += f;
}
void operator *= (long f)
{
x *= f;
y *= f;
z *= f;
}
void operator /= (long d)
{
x /= d;
y /= d;
z /= d;
}
};
#define MILLION 1000000
vector v1 = { 1.0, 2.0, 3.0 };
vector v2 = { 100.0, 200.0, 300.0 };
vector v3 = { 40.0, 50.0, 60.0 };
vector tmp1;
vector tmp2;
vector tmp3;
vector tmp;
int main()
{
tmp = v1;
tmp += 1;
if (tmp.x == 2.0 && tmp.y == 3.0 && tmp.z == 4.0)
printf("test1: Ok!\n");
tmp = v2;
tmp *= 2;
if (tmp.x == 200.0 && tmp.y == 400.0 && tmp.z == 600.0)
printf("test2: Ok!\n");
tmp = v3;
tmp /= 10;
if (tmp.x == 4.0 && tmp.y == 5.0 && tmp.z == 6.0)
printf("test3: Ok!\n");
TIME_BEGIN;
for (long i = 0; i < MILLION; ++i)
{
tmp1 = v1;
tmp1 += i;
tmp1 *= i;
tmp1 /= i;
tmp2 = v2;
tmp2 += i;
tmp2 *= i;
tmp2 /= i;
tmp3 = v3;
tmp3 += i;
tmp3 *= i;
tmp3 /= i;
}
TIME_END;
while (true);
return 0;
}
Edit: His code only takes about 5ms compared to mine, which takes about 500ms.
Last edited by DigiRev; Aug 3rd, 2009 at 07:37 PM.
-
Aug 3rd, 2009, 07:16 PM
#2
Re: Make this faster
Doesn't surprise me. Number crunching is what C/C++ does best. One of the reasons is that C/C++ will compile to native code, while VB, especially VB6 runs through an interpreter engine as it is running.
You can try changing the compile otions to compile to NAtive code, see if the EXE runs any faster that way.
There's a reason a lot of games and graphics intense applications are written in C/C++ and not VB.
-tg
-
Aug 3rd, 2009, 07:33 PM
#3
-
Aug 3rd, 2009, 07:36 PM
#4
Re: Make this faster
Not everything goes through the VB runtime, a lot gets compiled to true machine code.
I had more faith in VB than I should have, I guess. With well-written code it seems to perform really well. Maybe just not at math.
Anyway, we changed it to use Long instead of floating point, so if anyone has any ideas to make it faster, please post.
I updated original post with new code.
-
Aug 3rd, 2009, 07:37 PM
#5
Re: Make this faster
Sorry.. .that's not to say there isn't something that could be done... I've just never needed that level of speed like that, so I wouldn't know if there is something that could be done.
-tg
-
Aug 3rd, 2009, 09:14 PM
#6
Re: Make this faster
Doing this kind of speed comparison is on almost the pointless side. One thing that should be accounted for is that C++ compilers generally optimize a whole lot. This means they may remove code and actually not do what has been written. This in turn means that people who don't know this start thinking C++ would somehow be more awesome than it really is (at times). VB's compiler does optimization too, but being based on a very old C compiler it doesn't have that many tricks in it's sleeve. In this case I think the C++ compiler may very well just execute the very last iteration of the loop, because the variables are never used for anything else so an intelligent compiler could very well do that.
Speedwise, I think one of the issues is that you're using a Type. Also, the trust you have an API goes into vain: making a single API call costs a lot more processing power than you'd think, because VB does things such as tracking API errors automatically in the background, which means calling CopyMemory in VB6 takes far more time than it does in C++. The actual memory copy happens just as quickly, it is just all the other things that make things go slower than one would expect.
A better comparison could be done with something that actually does something worthwhile and prevents C++ compiler to do code removing optimizations. Like, parse some kind of file data. However, an optimized C++ will still be likely to be faster, because VB6 doesn't provide stuff such as bitshifting, so you're forced to use slower methods to get the same results.
Edit!
You can just remove LARGE_INTEGER and replace it with Currency. No need to make a conversion function.
Last edited by Merri; Aug 3rd, 2009 at 09:19 PM.
-
Aug 4th, 2009, 07:26 AM
#7
Re: Make this faster
 Originally Posted by Merri
Doing this kind of speed comparison is on almost the pointless side. One thing that should be accounted for is that C++ compilers generally optimize a whole lot. This means they may remove code and actually not do what has been written. This in turn means that people who don't know this start thinking C++ would somehow be more awesome than it really is (at times). VB's compiler does optimization too, but being based on a very old C compiler it doesn't have that many tricks in it's sleeve. In this case I think the C++ compiler may very well just execute the very last iteration of the loop, because the variables are never used for anything else so an intelligent compiler could very well do that.
Speedwise, I think one of the issues is that you're using a Type. Also, the trust you have an API goes into vain: making a single API call costs a lot more processing power than you'd think, because VB does things such as tracking API errors automatically in the background, which means calling CopyMemory in VB6 takes far more time than it does in C++. The actual memory copy happens just as quickly, it is just all the other things that make things go slower than one would expect.
A better comparison could be done with something that actually does something worthwhile and prevents C++ compiler to do code removing optimizations. Like, parse some kind of file data. However, an optimized C++ will still be likely to be faster, because VB6 doesn't provide stuff such as bitshifting, so you're forced to use slower methods to get the same results.
Edit!
You can just remove LARGE_INTEGER and replace it with Currency. No need to make a conversion function.
Those were my thoughts exactly. I even told him we should do something like file parsing and execution times would be much closer to each other.
At first, he noticed that the compiler actually removed most of the code, but then he changed it so that it didn't (as far as I know anyway).
I also ended up removing the CopyMemory call later on.
-
Aug 4th, 2009, 09:53 AM
#8
Addicted Member
Re: [RESOLVED] Make this faster
You can use DLL/OCX ... Make the stuff that need Speek on C++ DLL, ans use it with vb ...
 DoEvents
-
Aug 4th, 2009, 09:54 AM
#9
Addicted Member
Re: [RESOLVED] Make this faster
Make the stuff that need Speed (not speek sorry) xD
 DoEvents
-
Oct 5th, 2009, 06:01 AM
#10
Member
Re: [RESOLVED] Make this faster
//edit: I'm sorry for digging this out, was searching for something and stumbled over it. Didn't check the date 
You could do an Integer division instead of a floating point one and, if allowed, "inline" the type copy:
Code:
With tmp
.x = v1.x * i
.y = v1.y * i
.z = v1.z * i
.x = .x \ i
.y = .y \ i
.z = .z \ i
.x = .x + i
.y = .y + i
.z = .z + i
End With
.
.
.
This runs a lot faster, it takes about 150 ms on my old laptop instead of 700 ms. But it's still slow, compared to the C code, which takes 25 ms with speed optimizations (350 ms without).
Maybe this is because of missing operators like +=, -=, and so on.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|