Ich habe ein kleines Problem und kann keine zufriedenstellende Lösung dafür finden. Es gibt ein Byte-Array und ich brauche diese Bytes nach hohen 7 Bits sortiert, während die Reihenfolge der niedrigen Bits erhalten.Fast Inplace Art von Byte-Array
So ursprünglich sah es wie folgt aus:
// sort buf[N] to tmp[N]
uint offs[128+1]; uint c,i,s;
for(i=0; i<128; i++) offs[i]=0;
for(i=0; i<l; i++) offs[buf[i]>>1]++;
for(i=0,s=0; i<128; i++) c=offs[i], offs[i]=s, s+=c; offs[i]=s;
byte* tmp = new byte[N];
for(i=0; i<N; i++) c=buf[i], tmp[offs[c>>1]++]=c; // sort
Aber diese Blöcke sind groß genug (8M zur Zeit), und ich möchte mehrere Threads verwenden, und ein extra 8M pro Faden bemerkbar. So
Ich habe versucht, einige einfache Radixsort zu verwenden:
void radix(byte* buf, uint h, uint l, uint mask) {
uint p = (h+l)>>1, q = h;
uint i = offs[h], j = offs[l]-1; h = offs[p];
if((i<h) && (j>=h)) {
byte c = buf[i], d = buf[j];
while((i<h) && (j>=h)) {
while((c&mask)==0) c = buf[++i]; // find value with bit 1
while((d&mask)!=0) d = buf[--j]; // find value with bit 0
buf[i]=d; buf[j]=c; // swap 1-0 -> 0-1
c = buf[++i]; d = buf[--j];
}
if(mask>=4) {
radix(buf, q,p, mask>>1);
radix(buf, p,l, mask>>1);
}
}
}
Aber es ändert sich die Reihenfolge dieser niedrigen Bits und es wird unbrauchbar.
Eigentlich einige einfachere Methoden, wie bubblesort, nur tun, was ich will, aber sie sind viel langsamer, und Geschwindigkeit ist ein Problem zu.
Also ich derzeit sortieren kleinere Blöcke über einen temporären Puffer, dann eine Indextabelle verwenden teilweise sortierten Stücke, um den Zugriff auf:
struct tmpsort {
enum{ blocksize = (1<<16)-1 };
unsigned short ofs[(max_quants+blocksize-1)/blocksize][probN];
tmpsort(byte* buf, uint f_len) {
uint i,j,k;
uint freq[2*probN]; // prob freqs
byte tmp[blocksize+1];
for(k=0,j=0; k<f_len; k+=blocksize,j++) {
uint l = Min(k+blocksize,f_len)-k;
byte* p = &buf[k];
// compute offsets of sorted chunks
for(i=0; i<2*probN; i++) freq[i]=0;
for(i=0; i<l; i++) freq[p[i]]++;
for(i=0; i<probN; i++) freq[i+1]=freq[2*i+0]+freq[2*i+1]; // 1=0+1, 2=2+3, 3=4+5
freq[0] = 0;
for(i=0; i<probN; i++) freq[i+1]+=freq[i];
for(i=0; i<probN; i++) ofs[j][i]=freq[i+1];
// sort the block via tmp
for(i=0; i<l; i++) { byte c=p[i]; tmp[freq[c>>1]++]=c; }
for(i=0; i<l; i++) p[i]=tmp[i];
}
}
};
[...]
tmpsort ts(buf, f_len);
for(i=0; i<probN; i++) {
for(k=0,j=0; k<f_len; k+=ts.blocksize,j++) {
uint x = i>0 ? ts.ofs[j][i-1] : 0;
for(; x<ts.ofs[j][i]; x++) putc(buf[k+x],g);
}
}
Aber tmp [] und ofs [] Arrays verwenden zu viel Stack-Speicher und seine nicht eine vollständige Art, so frage ich mich, ob es eine saubere Lösung dafür gibt.
Eine Probe von Daten und meine Implementierungen sind hier verfügbar: http://nishi.dreamhosters.com/u/tmpsort_v0.rar
Danke, ich habe diesen Ansatz wirklich vermisst, könnte einen Versuch wert sein. – Shelwien