簡體   English   中英

從C ++中的字節數組中提取非零索引的最快方法是什么

[英]What's the fastest way to extract non-zero indices from a byte array in C++

我有一個字節數組

unsigned char* array=new unsigned char[4000000];
 ...

我想得到數組中所有非零元素的索引。

當然,我可以做到以下

for(int i=0;i<size;i++)
{
    if(array[i]!=0) somevector.push_back(i);
}

有比這更快的算法嗎?

更新1我可以看到多數回答是否定的。 我希望有一些我不知道的神奇位操作。 有些人建議排序,但在這種情況下並不可行。 但是非常感謝你的所有答案。

更新2自此問題發布4年零4個月后,@ wim建議這個答案看起來很有希望

除非您的矢量是有序的,否則如果您使用單線程程序,這是執行您想要執行的操作的最有效算法。 您可以嘗試優化要存儲結果的數據結構,但這是您能夠做到的最佳時間。

如果非零值相對較少,您可以使用的一個技巧是標記值:

unsigned char old_value = array[size-1];
array[size-1] = 1; // make sure we find a non-zero eventually

int i=0;

for (;;) {
  while (array[i]==0) ++i; // tighter loop
  if (i==size-1) break;
  somevector.push_back(i);
  ++i;
}

array[size-1] = old_value;
if (old_value!=0) {
  somevector.push_back(size-1);
}

這避免了必須在每次迭代時檢查索引和值。

對於一個大部分為零的字節數組,作為稀疏數組,您可以通過一次比較4個字節來利用32位CPU。 實際比較一次完成4個字節,但是如果任何字節都不為零,那么你必須確定無符號長整數中的哪些字節是非零的,因此需要花費更多精力。 如果數組實際上是稀疏的,則通過比較保存的時間可以補償確定哪些字節非零的額外工作。

最簡單的方法是將unsigned char數組的大小設置為4個字節的倍數,這樣您就不必擔心在循環完成后執行最后幾個字節。

我建議對此進行時序研究,因為它純粹是猜測的,並且有一個點,數組變得非稀疏,這比簡單的循環需要更多的時間。

我要問的一個問題是你用數組的非零元素的偏移向量做什么,以及你是否可以取消向量。 另一個問題是,如果您需要向量,是否可以在將元素放入數組時構建向量。

unsigned char* array=new unsigned char[4000000];
......
unsigned long *pUlaw = (unsigned long *)array;

for ( ; pUlaw < array + 4000000; pUlaw++) {
    if (*pUlaw) {
        // at least one byte is non-zero
        unsigned char *pUlawByte = (unsigned char *)pUlaw;
        if (*pUlawByte)
            somevector.push_back(pUlawByte - array);
        if (*(pUlawByte+1))
            somevector.push_back(pUlawByte - array + 1);
        if (*(pUlawByte+2))
            somevector.push_back(pUlawByte - array + 2);
        if (*(pUlawByte+3))
            somevector.push_back(pUlawByte - array + 3);
    }
}

您可以做的唯一提高速度的方法是使用並發。

這不是你問題的真正答案,但我試圖想象你想要解決的問題。

有時在矩陣上執行操作(在數學意義上),當您知道絕大多數矩陣元素將為零(稀疏矩陣)時,可以改進操作。 您可以通過不使用大數組來進行這樣的優化,而只需存儲指示非零元素的對{index,value}。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM