Avatar billede bjering Nybegynder
10. december 2007 - 09:41 Der er 29 kommentarer og
1 løsning

Har brug for en sindsyg hurtig array.

Hej Eksperter :)

Endnu engang kommer jeg krybene, fordi jeg har et stort problem

Har omkring 100.000 ting jeg skal smide i et array, map data.

data er

[int MapID] [int locX] [int locY] [int CellInfo]

kunne f.eks være

[1][32767[32689][4]
[1][32766[32689][4]
[1][32765[32689][4]
[1][32764[32689][2]

der er optil 100.000 af disse.

Jeg skal have fat i CellInfo via X,Y og MapID (skal match og så henter jeg cellinfo ud).

Array er vild langsom, og tror sq den dør når jeg smider så mange ind, den kan slet ikke få fat i dataen hurtig nok.

Nogen ide'er ?

Takker
Avatar billede bjering Nybegynder
10. december 2007 - 09:43 #1
den skal kunne hente cellinfo DIREKTE via mapid, locx, locy og ikke hamre igennem 99.999 linier for at hente cellinfo fra den sidste id.
Avatar billede the_party_dog Nybegynder
10. december 2007 - 09:47 #2
Hvordan gør du det idag, eller hvordan havde du tænkt på det første gang? Du har vel MapID, locX og locY oplysningerne ved hånden når du leder efter CellInfo oplysningen?
Avatar billede bjering Nybegynder
10. december 2007 - 09:58 #3
ja det har jeg

Player.Mapid, Player.X, Player.Y
Avatar billede the_party_dog Nybegynder
10. december 2007 - 10:02 #4
Hvordan finder du frem til CellInfo nu? Siden du siger den er vildt langsom, skal vide lidt mere før vi kan komme med nogle ideer :o)
Avatar billede bjering Nybegynder
10. december 2007 - 10:02 #5
det jeg prøvede sidst var 2 array lists

først havde:
public class map()
{
  public int id;
  public array<mapinfo>
}

public class mapinfo
{
  public int locx;
  public int locy;
  public int cellinfo;
}

så hentede jeg data ved at foreach på map først, så foreach på mapinfo, men det var aaaaalt for langsomt.
Avatar billede bjering Nybegynder
10. december 2007 - 10:02 #6
det var hvad jeg gør lige nu
Avatar billede sherlock Nybegynder
10. december 2007 - 10:06 #7
Du kan bruge det indbyggede DataTable.

Det kan bruges til rene Memorytabeller og der kan forespørges med f.ex. DataTable.Select("MapID = 23 and locX = 2343 and locY " 22");

http://msdn2.microsoft.com/en-us/library/system.data.datatable(VS.71).aspx
Avatar billede the_party_dog Nybegynder
10. december 2007 - 10:09 #8
Altså hvis du laver et multidimensioneret array, kan du så ikke "bare" udlæse data'en?

int Array[100][200][300][4]

Så burde du kunne hente det hele ved at skrive:
Array[MapID][locX][locY] - Hvis du så har flere pladser (CellInfo's) så er det her du skal lave en foreach.

Håber det giver lidt mening, sidder ikke med mit IDE tændt, så jeg kan ikke lige teste det hele igennem. Post gerne noget kode hvis du prøver mit forslag, så vil jeg se det igennem.
Avatar billede the_party_dog Nybegynder
10. december 2007 - 10:10 #9
Sherlock> Det var da et rigtig godt forslag, havde jeg slet ikke lige tænkt på :o)
Avatar billede bjering Nybegynder
10. december 2007 - 10:13 #10
hmm linken der funker ikke, skriver Content not found
Avatar billede md_craig Nybegynder
10. december 2007 - 10:17 #11
Så MapID + LocX + LocY er det der danne en unik "record" ?...
og det samme MapID kan godt gå igen, og det samme gælder for de andre?...

Så er det vel at danne en eller anden unik hash ud fra de 3 parametre og så bruge et HashTable til tingene?...
Avatar billede sherlock Nybegynder
10. december 2007 - 10:38 #12
Linket virker fint her ?!
Avatar billede bjering Nybegynder
10. december 2007 - 10:54 #13
okay, har lige prøvet med DataTable, den kan slet ikke holde alt det data.

den når 1700 maps igennem ca, så fryser den totalt...

        public static DataTable maplin = new DataTable("linmaps");
        public static DataColumn  myDataColumn;
        public static DataRow myDataRow;

        #region Constructor
        public MapLoader()
        {
            myDataColumn = new DataColumn();
            myDataColumn.DataType = System.Type.GetType("System.Int32");
            myDataColumn.ColumnName = "mapid";       
            maplin.Columns.Add(myDataColumn);

            myDataColumn = new DataColumn();
            myDataColumn.DataType = System.Type.GetType("System.Int32");
            myDataColumn.ColumnName = "locx";
            maplin.Columns.Add(myDataColumn);

            myDataColumn = new DataColumn();
            myDataColumn.DataType = System.Type.GetType("System.Int32");
            myDataColumn.ColumnName = "locy";
            maplin.Columns.Add(myDataColumn);

            myDataColumn = new DataColumn();
            myDataColumn.DataType = System.Type.GetType("System.Int32");
            myDataColumn.ColumnName = "cellinfo";
            myDataColumn.ReadOnly = false;
            maplin.Columns.Add(myDataColumn);
        }
        #endregion



og længere nede smider jeg data ind..

myDataRow = maplin.NewRow();
myDataRow["mapid"] = mapid;
myDataRow["locx"] = (startx + x);
myDataRow["locy"] = (starty + y);
myDataRow["cellinfo"] = cellinfo;
maplin.Rows.Add(myDataRow);

kan det ikke holde så meget data ?
Avatar billede nielle Nybegynder
10. december 2007 - 11:00 #14
Hvis du kigger på noget generics, vil du i hvert fald spare en hel den tid på boxing og unboxing. Og typecasting.
Avatar billede bjering Nybegynder
10. december 2007 - 11:00 #15
btw, hver map har 64*64 info, der er 3571 maps den skal loade.

der er så

14.626.816 cell's den skal gemme info for.
Avatar billede bjering Nybegynder
10. december 2007 - 11:02 #16
med real time access mere eller mindre
Avatar billede bjering Nybegynder
10. december 2007 - 11:03 #17
det må da kunne lade sig gøre...

jeg mener, det er jo ikke en bog hver gang, det er bare et par ints..
Avatar billede sherlock Nybegynder
10. december 2007 - 11:34 #18
Hvordan har du data liggende, udenfor programmet?
Avatar billede the_party_dog Nybegynder
10. december 2007 - 13:00 #19
Nu har jeg rodet lidt med det hele og fået tændt mit IDE, jeg kan altså ikke se hvad dit problem med et "almindeligt" multidimensional array skulle være?

public int[,,,] Temp = new int[3751,64,64,1];

private void button1_Click(object sender, EventArgs e)
        {
            int TempInt = 0;
            for (int i = 0; i < 3751; i++)
            {
                for (int j = 0; j < 64; j++)
                {
                    for (int h = 0; h < 64; h++)
                    {
                        Temp[i, j, h, 0] = TempInt > 0 ? 0 : 1;
                        TempInt = TempInt > 0 ? 0 : 1;
                    }
                }
            }

            MessageBox.Show("Done");
        }

private void button2_Click(object sender, EventArgs e)
        {
            int MapID = int.Parse(textBox1.Text);
            int locX = int.Parse(textBox2.Text);
            int locY = int.Parse(textBox3.Text);

            MessageBox.Show(Temp[MapID, locX, locY, 0].ToString());
        }

Det er lavet i en windows form, og jeg synes ikke responsetiden er særlig dårlig, du burde nok kunne lave det om til dit program og se hvordan det virker.
Avatar billede md_craig Nybegynder
10. december 2007 - 13:57 #20
class Program
    {

        const int CELLS = 64 * 64 * 3571;
        static int[, , ,] temp = new int[3751, 64, 64, 1];
        static int[] cell;

        static void Main(string[] args)
        {
            cell = new int[CELLS];
            for (int i = 0; i < CELLS; i++)
            {
                cell[i] = i % 4096;
            }

            int tint = 0;
            for (int i = 0; i < 3751; i++)
            {
                for (int j = 0; j < 64; j++)
                {
                    for (int h = 0; h < 64; h++)
                    {
                        temp[i, j, h, 0] = tint > 0 ? 0 : 1;
                        tint = tint > 0 ? 0 : 1;
                    }
                }
            }


            long performanceHelper = 0;
            HiPerfTimer timer = new HiPerfTimer();
            timer.Start();
            for (int i = 0; i < 100000000; i++)
                performanceHelper += cell[CalculateCellIndex((i * 21) % 3571, (byte)((i * 21) % 64), (byte)((i * 21) % 64))];
            timer.Stop();
            Console.WriteLine(timer.Duration);


            performanceHelper = 0;
            //HiPerfTimer timer = new HiPerfTimer();
            timer.Start();
            for (int i = 0; i < 100000000; i++)
                performanceHelper += temp[(i * 21) % 3571,((i * 21) % 64),((i * 21) % 64),0];
            timer.Stop();
            Console.WriteLine(timer.Duration);

        }

        static int CalculateCellIndex(int mapid, byte x, byte y)
        {
            return mapid & (x << 6) & (y << 12);
        }
    }

Ok, det kan godt være den overstående med CalculateCellIndex virker lidt hexet, ikke desto mindre performer den.

den piller 100.000.000 (og addere dem til den hjælpe variabel der er) på under 2 sekunder på den computer jeg sider på... Multidementionelt array bruger 8 sekunder...
Avatar billede md_craig Nybegynder
10. december 2007 - 14:01 #21
static int CalculateCellIndex(int mapid, byte x, byte y)
        {
            return (mapid << 12) & (x << 6) & y;
        }

Og dødt kode skal man ikke poste... o.O
Avatar billede bjering Nybegynder
10. december 2007 - 19:26 #22
jeg har nul forstand på int arrays.

hvorfor finder jeg f.eks

int cellinfo = mapinfo[map, locx, locy]; ?

i den der array, er der noget der skal være unikt ? og hvordan sætter jeg data ind direkte ?

jeg kører igennem et loop for at hente data ud af filen..

                    while (y < ysize)
                    {
                        int x = 1;
                        while (x < xsize)
                        {                           
                            int cellinfo = br.ReadInt16();
                            int cellinfo1 = br.ReadInt16();

                            maplin = new int[mapid, (startx + x), (starty + y), cellinfo];

                            x++;                           
                        }
                        y++;
                    }     


dette virker ikke ser det ud til :p
Avatar billede bjering Nybegynder
10. december 2007 - 19:43 #23
jeg vil også gerne pointere at lave en key med mapid+locx+locy kan ikke lade sig gøre

fordi den kan være
4,32500,32600
4,32600,32500
Avatar billede Syska Mester
10. december 2007 - 22:40 #24
ja, det er hvis du tager summen af dem ...

Tror de vil have dig til at lave dine 3 ints om til string for derefter at lave det om til en int ... så du reelt får:
43250032600
43260032500

Hvilket er 2 unikke tal ...

// ouT
Avatar billede the_party_dog Nybegynder
11. december 2007 - 13:12 #25
Skal vi ikke prøve at blive enige om nogle ting her, så vi kan hjælpe dig videre? :o)

Altså du har:
*3751 forskellige maps.
*Hvert map har 64 forskellige locX værdier.
*Hvert map har 64 forskellige locY værdier.
*Til sidst har du kun en CellInfo værdi.

Er det sådan din verden ser ud? Kan man måske få noget af filen, måske bare 1000 rækker, så man kan se hvad du arbejder med?

Men for at vise hvordan du kunne lave din kode:

public int[,,,] MapInfoArray = new int[3752,65,65,0];

//Dette skal declares uden for din funktion så den bliver public (Eller private hvis det er i den samme klasse), så vi kan rive fat i den på et andet sted i din kode.

while (y < ysize)
{
    int x = 1;
        while (x < xsize)
        {                           
            int cellinfo = br.ReadInt16();
                int cellinfo1 = br.ReadInt16();

        MapInfoArray[mapid, (startx + x), (starty + y), 0] = cellinfo;

        x++;                           
    }
        y++;
}     


Jeg går ud fra du får dit mapid et eller sted fra, fra selve filen? Men det har du sikkert styr på. Jeg kan se du sætter X=1 hver gang du løber igennem y, så jeg forventer du gør det samme med y uden for den yderste while løkke. Det du skal huske på er at arrays zero-index based, så deres første plads starter ved 0 (nul). Så jeg har udvidet arrayet så det kan håndtere du sætter den til 1, ellers vil du får en bound-exception omkring at du prøver at tilgå en plads i dit array som ikke er oprettet i hukommelse.

Hvis du laver en funktion minder om denne, så kan du udlæse værdien fra cellinfo baseret på Mapid, locX, locY:

private int ReadCellInfo(int intMapID, int intlocX, int intlocY)
{
    return MapInfoArray[intMapID, intlocX, intlocY, 0];
}
Avatar billede md_craig Nybegynder
11. december 2007 - 15:18 #26
bjering >>>

return (mapid << 12) & (x << 6) & y;

Den pakker de 3 værdier sammen i en enkelt integer hvor de ligger i hver deres bit områder...

y ligger på bit 0-6
x ligger på bit 7-12
mapid ligger på bit 13-32
(mapid kræver dog kun op til bit 24)...

så længe 2 ens kombinationer ikke findes, vil tallet du får ud af det være unikt...

(<< er en shift operator skubber bitsne i en datatype med x antal bits, at lave dem om til tal, concate og samle igen er alt for ineffektivt)
Avatar billede the_party_dog Nybegynder
11. december 2007 - 16:40 #27
md_craig>>

Det var jo faktisk lettere genialt det du har lavet, jeg havde nok set du lavede en bitshifting, men kunne ikke lige gennemskue hvorfor og hvorfor du lavede en modolus 4096 på i variablen i din første løkke. Men nu begynder det hele at falde på plads, fordi du kun brugere et stort array med alle pladser og håndtere index håndteringen i en int variable vha. bit shifting...

Se det er kreativ tanke gang :-D
Avatar billede md_craig Nybegynder
13. december 2007 - 08:17 #28
the_party_dog >>

Da jeg ikke havde nogen ide om hvad for noget der skulle lagres som "cellinfo" så smed jeg bare et eller andet i... og det blev til en i % 4096 (så har alle cells på et kort sit eget id)... så går jeg derfra ud fra at bjering selv kan smide den korekte information i :)...
Avatar billede bjering Nybegynder
10. august 2008 - 01:52 #29
lukker, ingen svar
Avatar billede Syska Mester
11. august 2008 - 00:33 #30
Synes da der er masser af svar, men du har ikke rigtig kommenteret nogen af dem.

Dvs ... Masser af svar, men du har fundet en anden løsning ?

// ouT
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester