Gå til innhold

Anbefalte innlegg

Videoannonse
Annonse

LonelyMan, du har rett, jeg hadde et par bugs i koden.

Har nå tatt i bruk den nye implementasjonen av randomStrGen fra jonny, i tillegg til å faktisk kalle funksjonen som genererer den nye tabellen.

Throughput er omtrent den samme dog;

100 Megabytes took 14.896170 milliseconds.

MB/s = 6713.135208

 

Assembly:

 

 

 

; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.40219.01
TITLE C:\Users\xxx\documents\visual studio 2010\Projects\Rot13Test\Rot13Test\rot13.cpp
.686P
.XMM
include listing.inc
.model flat
INCLUDELIB OLDNAMES
PUBLIC ?PCFreq@@3NA	 ; PCFreq
PUBLIC ?CounterStart@@3_JA    ; CounterStart
PUBLIC ??_C@_0DF@MEPDHLIP@abcdefghijklmnopqrstuvwxyzABCDEF@ ; `string'
PUBLIC ??_C@_0BD@ONNLNDEL@QPC?5did?5not?5work?4?4?$AA@ ; `string'
PUBLIC ??_C@_0CF@MOIGNLJO@100?5Megabytes?5took?5?$CFf?5millisecon@ ; `string'
PUBLIC ??_C@_09IJINBEEB@MB?1s?5?$DN?5?$CFf?$AA@ ; `string'
EXTRN __imp__QueryPerformanceFrequency@4:PROC
EXTRN __imp__QueryPerformanceCounter@4:PROC
EXTRN __imp__free:PROC
EXTRN __imp__malloc:PROC
EXTRN __imp__printf:PROC
EXTRN __imp__rand:PROC
EXTRN __imp__srand:PROC
EXTRN __imp___time64:PROC
?PCFreq@@3NA DQ 01H DUP (?)    ; PCFreq
?CounterStart@@3_JA DQ 01H DUP (?)   ; CounterStart
; COMDAT ??_C@_09IJINBEEB@MB?1s?5?$DN?5?$CFf?$AA@
CONST SEGMENT
??_C@_09IJINBEEB@MB?1s?5?$DN?5?$CFf?$AA@ DB 'MB/s = %f', 00H ; `string'
CONST ENDS
; COMDAT ??_C@_0CF@MOIGNLJO@100?5Megabytes?5took?5?$CFf?5millisecon@
CONST SEGMENT
??_C@_0CF@MOIGNLJO@100?5Megabytes?5took?5?$CFf?5millisecon@ DB '100 Megab'
DB 'ytes took %f milliseconds.', 0aH, 00H ; `string'
CONST ENDS
; COMDAT ??_C@_0BD@ONNLNDEL@QPC?5did?5not?5work?4?4?$AA@
CONST SEGMENT
??_C@_0BD@ONNLNDEL@QPC?5did?5not?5work?4?4?$AA@ DB 'QPC did not work..', 00H ; `string'
CONST ENDS
; COMDAT ??_C@_0DF@MEPDHLIP@abcdefghijklmnopqrstuvwxyzABCDEF@
CONST SEGMENT
??_C@_0DF@MEPDHLIP@abcdefghijklmnopqrstuvwxyzABCDEF@ DB 'abcdefghijklmnop'
DB 'qrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 00H ; `string'
CONST ENDS
PUBLIC ?createLookupWide@@YAXXZ   ; createLookupWide
_lookupWide DW 010000H DUP (?)
_lookup DB 0100H DUP (?)
; Function compile flags: /Ogtp
; COMDAT ?createLookupWide@@YAXXZ
_TEXT SEGMENT
?createLookupWide@@YAXXZ PROC    ; createLookupWide, COMDAT
; File c:\users\xxx\documents\visual studio 2010\projects\rot13test\rot13test\rot13.cpp
; Line 91
xor eax, eax
$LL3@createLook:
; Line 93
mov ecx, eax
sar ecx, 8
; Line 95
movsx edx, cl
movsx cx, BYTE PTR _lookup[edx]
movsx edx, al
movzx edx, BYTE PTR _lookup[edx]
shl cx, 8
or cx, dx
mov WORD PTR _lookupWide[eax*2], cx
inc eax
cmp eax, 65536    ; 00010000H
jl SHORT $LL3@createLook
; Line 132
ret 0
?createLookupWide@@YAXXZ ENDP    ; createLookupWide
_TEXT ENDS
PUBLIC ?createLookup@@YAXXZ    ; createLookup
; Function compile flags: /Ogtp
; COMDAT ?createLookup@@YAXXZ
_TEXT SEGMENT
?createLookup@@YAXXZ PROC    ; createLookup, COMDAT
; Line 63
xor eax, eax
$LL13@createLook@2:
; Line 64
mov BYTE PTR _lookup[eax], al
inc eax
cmp eax, 256    ; 00000100H
jl SHORT $LL13@createLook@2
; Line 67
mov eax, 65	 ; 00000041H
$LL10@createLook@2:
; Line 68
cmp eax, 77	 ; 0000004dH
jg SHORT $LN7@createLook@2
; Line 69
lea ecx, DWORD PTR [eax+13]
mov BYTE PTR _lookup[eax], cl
; Line 70
jmp SHORT $LN9@createLook@2
$LN7@createLook@2:
; Line 71
lea edx, DWORD PTR [eax-13]
mov BYTE PTR _lookup[eax], dl
$LN9@createLook@2:
; Line 67
inc eax
cmp eax, 90	 ; 0000005aH
jle SHORT $LL10@createLook@2
; Line 75
mov eax, 97	 ; 00000061H
npad 7
$LL5@createLook@2:
; Line 76
cmp eax, 109    ; 0000006dH
jg SHORT $LN2@createLook@2
; Line 77
lea ecx, DWORD PTR [eax+13]
mov BYTE PTR _lookup[eax], cl
; Line 78
jmp SHORT $LN4@createLook@2
$LN2@createLook@2:
; Line 79
lea edx, DWORD PTR [eax-13]
mov BYTE PTR _lookup[eax], dl
$LN4@createLook@2:
; Line 75
inc eax
cmp eax, 122    ; 0000007aH
jle SHORT $LL5@createLook@2
; Line 82
ret 0
?createLookup@@YAXXZ ENDP    ; createLookup
_TEXT ENDS
PUBLIC ?stringRotation@@YAXPAEH@Z   ; stringRotation
; Function compile flags: /Ogtp
; COMDAT ?stringRotation@@YAXPAEH@Z
_TEXT SEGMENT
?stringRotation@@YAXPAEH@Z PROC    ; stringRotation, COMDAT
; _text$ = eax
; Line 52
inc eax
mov ecx, 5000000    ; 004c4b40H
npad 10
$LL3@stringRota:
; Line 57
movzx edx, BYTE PTR [eax-1]
movzx edx, BYTE PTR _lookupWide[edx*2]
mov BYTE PTR [eax-1], dl
movzx edx, BYTE PTR [eax]
movzx edx, BYTE PTR _lookupWide[edx*2]
mov BYTE PTR [eax], dl
movzx edx, BYTE PTR [eax+1]
movzx edx, BYTE PTR _lookupWide[edx*2]
mov BYTE PTR [eax+1], dl
movzx edx, BYTE PTR [eax+2]
movzx edx, BYTE PTR _lookupWide[edx*2]
mov BYTE PTR [eax+2], dl
movzx edx, BYTE PTR [eax+3]
movzx edx, BYTE PTR _lookupWide[edx*2]
mov BYTE PTR [eax+3], dl
add eax, 5
dec ecx
jne SHORT $LL3@stringRota
; Line 59
ret 0
?stringRotation@@YAXPAEH@Z ENDP    ; stringRotation
_TEXT ENDS
PUBLIC ?GetCounter@@YANXZ    ; GetCounter
EXTRN __fltused:DWORD
; Function compile flags: /Ogtp
; COMDAT ?GetCounter@@YANXZ
_TEXT SEGMENT
tv73 = -8	  ; size = 8
_li$ = -8	  ; size = 8
?GetCounter@@YANXZ PROC	 ; GetCounter, COMDAT
; Line 22
push ebp
mov ebp, esp
sub esp, 8
; Line 24
lea eax, DWORD PTR _li$[ebp]
push eax
call DWORD PTR __imp__QueryPerformanceCounter@4
; Line 25
mov ecx, DWORD PTR _li$[ebp]
sub ecx, DWORD PTR ?CounterStart@@3_JA
mov edx, DWORD PTR _li$[ebp+4]
sbb edx, DWORD PTR ?CounterStart@@3_JA+4
mov DWORD PTR tv73[ebp], ecx
mov DWORD PTR tv73[ebp+4], edx
fild QWORD PTR tv73[ebp]
fdiv QWORD PTR ?PCFreq@@3NA   ; PCFreq
; Line 26
mov esp, ebp
pop ebp
ret 0
?GetCounter@@YANXZ ENDP	 ; GetCounter
_TEXT ENDS
PUBLIC __real@408f400000000000
PUBLIC ?StartCounter@@YAXXZ    ; StartCounter
; COMDAT __real@408f400000000000
CONST SEGMENT
__real@408f400000000000 DQ 0408f400000000000r ; 1000
; Function compile flags: /Ogtp
CONST ENDS
; COMDAT ?StartCounter@@YAXXZ
_TEXT SEGMENT
_li$ = -8	  ; size = 8
?StartCounter@@YAXXZ PROC    ; StartCounter, COMDAT
; Line 11
push ebp
mov ebp, esp
sub esp, 8
; Line 13
lea eax, DWORD PTR _li$[ebp]
push eax
call DWORD PTR __imp__QueryPerformanceFrequency@4
test eax, eax
je SHORT $LN2@StartCount
; Line 16
fild QWORD PTR _li$[ebp]
; Line 18
lea ecx, DWORD PTR _li$[ebp]
push ecx
fdiv QWORD PTR __real@408f400000000000
fstp QWORD PTR ?PCFreq@@3NA   ; PCFreq
call DWORD PTR __imp__QueryPerformanceCounter@4
; Line 19
mov edx, DWORD PTR _li$[ebp]
mov eax, DWORD PTR _li$[ebp+4]
mov DWORD PTR ?CounterStart@@3_JA, edx
mov DWORD PTR ?CounterStart@@3_JA+4, eax
$LN2@StartCount:
; Line 20
mov esp, ebp
pop ebp
ret 0
?StartCounter@@YAXXZ ENDP    ; StartCounter
; Function compile flags: /Ogtp
_TEXT ENDS
; COMDAT _time
_TEXT SEGMENT
_time PROC	  ; COMDAT
; File c:\program files (x86)\microsoft visual studio 10.0\vc\include\time.inl
; Line 133
push 0
call DWORD PTR __imp___time64
add esp, 4
; Line 134
ret 0
_time ENDP
; Function compile flags: /Ogtp
_TEXT ENDS
; COMDAT ?randomStrGen@@YAXPAEH@Z
_TEXT SEGMENT
?randomStrGen@@YAXPAEH@Z PROC    ; randomStrGen, COMDAT
; _str$ = ebx
; File c:\users\xxx\documents\visual studio 2010\projects\rot13test\rot13test\rot13.cpp
; Line 40
push esi
push edi
; Line 41
push 0
call DWORD PTR __imp___time64
push eax
call DWORD PTR __imp__srand
; Line 43
mov edi, DWORD PTR __imp__rand
add esp, 8
xor esi, esi
npad 4
$LL3@randomStrG:
; Line 44
call edi
and eax, -2147483393   ; 800000ffH
jns SHORT $LN10@randomStrG
dec eax
or eax, -256    ; ffffff00H
inc eax
$LN10@randomStrG:
mov BYTE PTR [esi+ebx], al
inc esi
cmp esi, 99999999    ; 05f5e0ffH
jl SHORT $LL3@randomStrG
; Line 45
pop edi
pop esi
ret 0
?randomStrGen@@YAXPAEH@Z ENDP    ; randomStrGen
_TEXT ENDS
PUBLIC __real@4059000000000000
PUBLIC __real@0000000000000000
PUBLIC _main
EXTRN _memset:PROC
; COMDAT __real@4059000000000000
CONST SEGMENT
__real@4059000000000000 DQ 04059000000000000r ; 100
CONST ENDS
; COMDAT __real@0000000000000000
CONST SEGMENT
__real@0000000000000000 DQ 00000000000000000r ; 0
; Function compile flags: /Ogtp
CONST ENDS
; COMDAT _main
_TEXT SEGMENT
tv166 = -8	  ; size = 8
_li$67108 = -8	  ; size = 8
_li$67103 = -8	  ; size = 8
_li$67098 = -8	  ; size = 8
_durationMS$ = -8	 ; size = 8
_argc$ = 8	  ; size = 4
_argv$ = 12	  ; size = 4
_main PROC	  ; COMDAT
; Line 136
push ebp
mov ebp, esp
and esp, -64    ; ffffffc0H
sub esp, 52	 ; 00000034H
push ebx
push esi
push edi
; Line 140
push 100000000    ; 05f5e100H
call DWORD PTR __imp__malloc
add esp, 4
; Line 141
push 100000000    ; 05f5e100H
mov edi, eax
push 0
push edi
call _memset
add esp, 12	 ; 0000000cH
; Line 142
push 0
call DWORD PTR __imp___time64
add esp, 4
push eax
call DWORD PTR __imp__srand
mov ebx, DWORD PTR __imp__rand
add esp, 4
xor esi, esi
npad 7
$LL6@main:
call ebx
and eax, -2147483393   ; 800000ffH
jns SHORT $LN21@main
dec eax
or eax, -256    ; ffffff00H
inc eax
$LN21@main:
mov BYTE PTR [esi+edi], al
inc esi
cmp esi, 99999999    ; 05f5e0ffH
jl SHORT $LL6@main
; Line 145
call ?createLookup@@YAXXZ   ; createLookup
; Line 146
call ?createLookupWide@@YAXXZ  ; createLookupWide
; Line 149
mov ebx, DWORD PTR __imp__QueryPerformanceFrequency@4
lea eax, DWORD PTR _li$67098[esp+64]
push eax
call ebx
mov esi, DWORD PTR __imp__QueryPerformanceCounter@4
test eax, eax
je SHORT $LN12@main
fild QWORD PTR _li$67098[esp+64]
lea ecx, DWORD PTR _li$67098[esp+64]
push ecx
fdiv QWORD PTR __real@408f400000000000
fstp QWORD PTR ?PCFreq@@3NA   ; PCFreq
call esi
mov edx, DWORD PTR _li$67098[esp+64]
mov eax, DWORD PTR _li$67098[esp+68]
mov DWORD PTR ?CounterStart@@3_JA, edx
mov DWORD PTR ?CounterStart@@3_JA+4, eax
$LN12@main:
; Line 150
fld QWORD PTR ?PCFreq@@3NA   ; PCFreq
fldz
fucompp
fnstsw ax
test ah, 68	 ; 00000044H
jp SHORT $LN1@main
; Line 152
push OFFSET ??_C@_0BD@ONNLNDEL@QPC?5did?5not?5work?4?4?$AA@
call DWORD PTR __imp__printf
add esp, 4
; Line 153
mov eax, 1
; Line 171
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
$LN1@main:
; Line 157
lea ecx, DWORD PTR _li$67103[esp+64]
push ecx
call ebx
test eax, eax
je SHORT $LN15@main
fild QWORD PTR _li$67103[esp+64]
lea edx, DWORD PTR _li$67103[esp+64]
push edx
fdiv QWORD PTR __real@408f400000000000
fstp QWORD PTR ?PCFreq@@3NA   ; PCFreq
call esi
mov eax, DWORD PTR _li$67103[esp+64]
mov ecx, DWORD PTR _li$67103[esp+68]
mov DWORD PTR ?CounterStart@@3_JA, eax
mov DWORD PTR ?CounterStart@@3_JA+4, ecx
$LN15@main:
; Line 159
mov eax, edi
call ?stringRotation@@YAXPAEH@Z  ; stringRotation
; Line 161
lea edx, DWORD PTR _li$67108[esp+64]
push edx
call esi
mov eax, DWORD PTR _li$67108[esp+64]
sub eax, DWORD PTR ?CounterStart@@3_JA
mov ecx, DWORD PTR _li$67108[esp+68]
sbb ecx, DWORD PTR ?CounterStart@@3_JA+4
mov DWORD PTR tv166[esp+64], eax
mov DWORD PTR tv166[esp+68], ecx
fild QWORD PTR tv166[esp+64]
; Line 164
mov esi, DWORD PTR __imp__printf
sub esp, 8
fdiv QWORD PTR ?PCFreq@@3NA   ; PCFreq
fst QWORD PTR _durationMS$[esp+72]
fstp QWORD PTR [esp]
push OFFSET ??_C@_0CF@MOIGNLJO@100?5Megabytes?5took?5?$CFf?5millisecon@
call esi
; Line 165
fld QWORD PTR __real@4059000000000000
fdiv QWORD PTR _durationMS$[esp+76]
; Line 166
add esp, 4
fmul QWORD PTR __real@408f400000000000
fstp QWORD PTR [esp]
push OFFSET ??_C@_09IJINBEEB@MB?1s?5?$DN?5?$CFf?$AA@
call esi
add esp, 12	 ; 0000000cH
; Line 169
push edi
call DWORD PTR __imp__free
add esp, 4
; Line 171
pop edi
pop esi
xor eax, eax
pop ebx
mov esp, ebp
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END

 

 

Edit: Kommenterte ut noe ubrukt kode i createLookupWide.

Endret av Paull
Lenke til kommentar

Aprilspøk? Laget bare lookup-bufferet basert på 2 bytes istedet for 1:

 

 

 

 

#include <Windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
double PCFreq = 0.0;
__int64 CounterStart = 0;
void StartCounter()
{
LARGE_INTEGER li;
if(!QueryPerformanceFrequency(&li))
	return;
PCFreq = double(li.QuadPart)/1000.0;
QueryPerformanceCounter(&li);
CounterStart = li.QuadPart;
}
double GetCounter()
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
return double(li.QuadPart-CounterStart)/PCFreq;
}
static char lookup[256];
static short lookupWide[65536];
static void randomStrGen(unsigned char *str, int length) {
 srand(time(NULL));
 int i;
 for (i = 0; i < length; i++)
	str[i] = rand() % 256;
}
void stringRotation(unsigned char *text, int len) {
 int i;
 int tmp;
 short low;
 short high;
 int intLen = len / (sizeof(int) / sizeof(char));
 for(i = 0; i < intLen; i++)
 {
  tmp = text[i];
  low = (tmp & 0xFFFF);
  high = ((tmp >> 16) & 0xFFFF);
  text[i] = ((lookupWide[high] << 16 & 0xFFFF0000) | (lookupWide[low] & 0xFFFF));
 }
}
void createLookup() {
 int c;
 for (c = 0; c < 256; c++) {
	lookup[c] = c;
 }
 for (c = 'A'; c <= 'Z' ; c++) {
	if (c <= 'M') {
	  lookup[c] = c + 13;
	} else {
	  lookup[c] = c - 13;
	}
 }
 for (c = 'a'; c <= 'z'; c++) {
	if (c <= 'm') {
	  lookup[c] = c + 13;
	} else {
	  lookup[c] = c - 13;
	}
 }
}

void createLookupWide() {
char firstChar;
char secondChar;
short tmp = 0;
for(int x = 0; x < 65536; x++)
{
 firstChar = (x >> 8) & 0xFF;
 secondChar = (x & 0xFF);
 lookupWide[x] = ((lookup[firstChar] << 8) & 0x0000FF00) | (lookup[secondChar] & 0xFF);
}
}

int main(int argc, char *argv[])
{
 // Build test string
 int size = 1000000 * 100;
 unsigned char *test = (unsigned char*) malloc(size);
 memset(test, 0, size);
 randomStrGen(test, size-1);
 // Build lookuptables
 createLookup();
 createLookupWide();
 // Test QPC
 StartCounter();
 if(PCFreq == 0.0)
 {
  printf("QPC did not work..");
  return 1;
 }
 // Start
 StartCounter();
 stringRotation(test, size);
 double durationMS = GetCounter();
 printf("100 Megabytes took %f milliseconds.\n", durationMS);
 double megabyterPerSec = (100.0/(durationMS)) * 1000.0;
 printf("MB/s = %f", megabyterPerSec);
 // Done
 free(test);
 return 0;
}

 

 

Lenke til kommentar

Paull, den leser fortsatt 25 millioner bytes og skriver fortsatt 25 millioner bytes, altså 1/4 av hva den skal gjøre. Jeg fatter ikke hvordan du kan gå fra 6 millisekunder til 14 millisekunder med den samme koden. Det er helt utrolig spør du meg.

 

Den forandringen du gjorde med 52 bytes vs 256 har absolutt ingen effekt på koden du la frem nå, hvordan du gikk fra 6 til 14 ms er et data-under. :)

Endret av LonelyMan
Lenke til kommentar

Nei den leser ikke ints, den leser bytes. Den caster en byte til en int, og dermed leser du en fjerdedel av bufferen. I c++ koden din er det vanskelig å se det, men i assembler koden er det absolutt åpenbart.

 

Her caster den:

 

tmp = text[i];

 

Det er veldig lett å gjøre feil i kodingen så det gjør ingenting, lov å skrive feil. Jeg forsøker på ingen måte å være bombastisk her, jeg er bare dønn ærlig og sier ting som de er. Jeg er bare nødt å peke ut dette, for det er en grov feil. Jeg har gjort mange slike feil i høynivåspråk, ting er så kompakt i høynivåspråk at det er lett å overse en bagatell. I assembler så virker nesten ingenting av koden om noe er feil så der er det lett å gjøre ting riktig, hvis noe ikke er riktig så er sjansen stor for at ingenting fungerer i det hele tatt. ;)

Endret av LonelyMan
Lenke til kommentar

Jeg fikk ikke koden til Paull til å gjøre roteringa raskere på min prosessor, men benyttet meg av hans idé om å bruke en 16-bits lookup-table med følgende kode:

 

void stringRotation2(unsigned char *text, int len) {
 int align_offset = (unsigned long)text % UL_SIZE;
 int i = 0;
 if (align_offset > 0) {
for (; i < UL_SIZE - align_offset; i++) {
  int tmp = text[i];
  text[i] = lookup[tmp];
}
 }
 if (UL_SIZE == 8) {
for (; i <= len - UL_SIZE; i += UL_SIZE) {
  unsigned long *bytesPtr = (unsigned long *)&text[i];
  unsigned long oldval = *bytesPtr;
  unsigned long newval = lookups[oldval & 0xffff]; oldval >>= 16;
  newval |= (unsigned long)(lookups[oldval & 0xffff]) << 16; oldval >>= 16;
  newval |= (unsigned long)(lookups[oldval & 0xffff]) << 32; oldval >>= 16;
  newval |= (unsigned long)(lookups[oldval & 0xffff]) << 48;
  *bytesPtr = newval;
}
 } else if (UL_SIZE == 4) {
for (; i <= len - UL_SIZE; i += UL_SIZE) {
  unsigned long *bytesPtr = (unsigned long *)&text[i];
  unsigned long oldval = *bytesPtr;
  unsigned long newval = lookups[oldval & 0xffff]; oldval >>= 16;
  newval |= (unsigned long)(lookups[oldval & 0xffff]) << 16;
  *bytesPtr = newval;
}
 }
 for (; i < len; i++) {
int tmp = text[i];
text[i] = lookup[tmp];
 }
}

Denne funksjonen blir ferdig ila. 60 ms på min prosessor (lookups er 16-bit-lookup-tabellen).

Endret av jonny
Lenke til kommentar

Antoweif, norsk tipping sine egne nettsider sier følgende om 7 rette:

 

"I teorien kan man si at det er bortimot umulig å få sju rette, men på den annen side er det i gjennomsnitt fire personer som opplever dette hver eneste lørdag."

 

:hm:

 

Når ukene i programmet når 500 tusen uker, så vil det si at den norske befolkningen har spilt èn gang, men for deg vil det si at du har spilt 500 tusen ganger. Det er ca 500k spillere i Norge.

Endret av LonelyMan
Lenke til kommentar

Når det gjelder hvor raskt en kan skrive i assembly, så skal en heller ikke undervurdere det, der er mange direktiver og makroinstruksjoner som gjør ting ekstremt effektivt. Dette nibbles spillet jeg legger vedlagt har jeg skrevet på en dag. Det er ikke ferdig, og det er kun første level (ingen vegger på første level)

 

Den er skrevet for 4 kjerner prosessorer og bør kjøres på en slik cpu. Last ned hvis du vil teste. Skrevet i helt ren assembler.

 

Det hadde ikke vært nødvendig å bruke 4 kjerner da spillet er så lite krevende. Men det har betydning på keyboard polling.

 

1 kjerne rendererer grafikk

2 kjerne trekker taster fra tastaturet

3 kjerne genererer random tall for plassering av matbiter

4 kjerne genererer høypresisjons game-tick

 

Virker som 2 kjerner brukes 100% kontinuerlig. Bevegelsen til ormen er heller ikke glatte, den rykker litt nå og da. Men ganske artig :)

Lenke til kommentar

En kjerne kjører keyboard polling kontinuerlig så den vil ha høy load, den andre genererer ticks hvert millisekund og vil også ha høy load, men ikke like mye som keyboard pollingen.

 

De to andre vil ha lav load. Når det gjelder hakkingen så er det noe feil med tick-synkroniseringen som gjør at tiden akkumulerer opp over en viss tid og genererer et tick for mye. Antar jeg. Dette er GDI dog, ikke direct3d. Jeg har laget et nibbles spill i direct3d også, men det er i høynivåspråk, og den har funny grafikk i motsetning til denne jeg laget nå.

 

Lurer på om den ennå hakker av og til?

Nibbles.rar

Endret av LonelyMan
Lenke til kommentar

Det er ikke noe poeng å ha en egen tråd for å pollle tastaturet: ikke les inn data du ikke har tenkt til å bruke.

Istedet for en egen tick tråd, så kan du istedet bare regne ut delta-tid fra forrige frame-tick og bruke det som en multiplikator for hvor mye verden skal bevege seg. Dette kan du da lett bruke for å også legge ut epler. Da vil du sitte igjen med to tråder.

Lenke til kommentar

Om du bruker delta tiden så må du bruke performance counters, og denne delta tiden vil før eller senere føre til et at det blir et frame for mye eller for lite. Det fungerer bra i et 3d spill hvor du roterer verden for der vil du ikke merke denne frame-kickingen, og de fleste spill er 3d spill nå om dagene. Men i nibbles som dette jeg har laget så må du unngå delta timing.

 

Istedet for å bruke delta så kan du utnytte "naturlovene" i datamaskinen slik at den tiden det tar å kjøre koden akkumulerer opp slik at timingen BLIR den tiden du behøver uansett, uten å kalkulere delta tiden.

 

F.eks når du skal time en bit av koden din for å se hvor raskt den kjører, så kjører du kanskje slik:

 

TimeStart

Kjør kode

TimeSlutt

 

API funksjonen du bruker for start har også en viss kjøretid, ikke mye, men den har litt. Men det har også slutt api funksjonen også.

 

om TimeStart hypotetisk sett kjører på 50 mikrosekunder

 

og TimeSlutt også kjører på 50 mikrosekunder, så ender du opp uten å måtte kalkulere delta tid uansett.

 

for 50 + x + 50 så ender du opp med samme tiden du behøver. Det er bedre å la systemet ta seg av delta på en naturlig måte.

 

Når det gjelder keyboard pollingen så BEHØVER jeg ikke å kjøre i en egen tråd som jeg sa tidligere jeg hadde ikke behøvd å kjøre 4 tråder med nibbles. Men det har likevel effekt på keyboard pollingen.

 

Det eneste unntaket er hvis jeg bruker rawinput eller directinput. Jeg har skrevet rutiner for å bruke rawinput, men jeg orker ikke legge det inn.

 

Om du skal bruke vanlige windows beskjeder for å handle keyboard så kjøres beskjedene lineært, og problemet med å handle keyboard polling lineært er at om den som spiller ombestemmer tastetrykket sitt før ormen har snudd seg, så vil det oppstå et mikrosekunds feil slik at ormen ikke snur seg likevel. Fordi rendereringen og handlingen av ormen tar litt tid å kjøre, det er ikke slik at du ikke rekker å trykke om du ikke brukte en egen tråd, men det jeg sier er at om brukeren trykker en annen tast så vil han med et uhell ville oppleve å miste tastetrykket sitt iblant, og dette uhellet oppleves i spillet, men ikke nå når jeg kjører pollingen i egen tråd.

 

Lettere å forklare med punkter:

 

1. Ormen beveges og rendereres (noe pre-code kjører for å forberede dette)

2. Koden har forberedt bevegelser og er nå ready for å lese keyboard pollingen

3. brukeren trykket ny retning og den nye retningen er registrert

4. koden beveger ormen

 

Det er vanskelig å forstå, men tastetrykk for ormen er meget kompleks, selv om det er et enkelt spill, og denne kompleksiteten gjør det bedre å kjøre i egen tråd. Jeg kunne forklart hvordan tastetrykkene fungerer, men litt senere.

 

Om du likevel ikke skulle brukt egen tråd til dette og bare polle tastetrykket idet du rendererer og tegner ormen, så ville du på lik linje mistet noen mikrosekunders FORTID. Og samme problemet oppstår. :)

Endret av LonelyMan
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...