2012-02-10 6 views
1

a3[]長さL1、L2のそれぞれ、I 3つの倍精度アレイa1[]a2[]があるとしたバーチャルコンカチネーション、L3アレイ

は、それは私が仮想 を作成したいです「事実」私はこれらの配列を連結したいと配列a_virtual[]のように、論理的にはa_virtual = {a1[L1], a2[L2], a3[L3]}であるが、物理的にはこれらの配列は互いに連続していなくてもよい。私はa_virtual[5]L1=2L2=3L3=1にアクセスしたい場合は

それではa3[0]がフェッチされます。 a_virtual[0]にアクセスするための、a1[0]

私はC++(STDでこれを行う方法::配列の代わりにベクトルが も有用であろう)で、この

  • C
  • をどのように行うだろうフェッチされますCUDA

  • は、私はそれを行う方法がある場合、それはすべての3つの環境で同じになりますが、メートルがあるかもしれない疑いそれぞれの環境内でこれを行う効率的な方法は、 の機能に依存します。

  • +0

    なぜ配列が連続していないのですか?なぜ彼らはできないのですか?それはこの問題をはるかに容易にします。 – Patrick87

    +0

    CUDAのケースでは、可能な場合であっても、それをやりたいとは思わないでしょう。ホスト→デバイスのメモリ転送の一環として、ホスト側の "フラット"コピーまたは "zip"演算子は、はるかに賢明な考えです。 – talonmies

    +0

    あなたが理解できないこの問題については何ですか? – asveikau

    答えて

    1

    は、リンクリストおよび(テール)再帰を使用して、Cで可能なソリューションです:

    #include <stdio.h> 
    
    struct dblarr { 
        double *data; 
        size_t len; 
        struct dblarr *next; 
    }; 
    
    double *fetch(const struct dblarr *arr, size_t index) { 
        if (arr == NULL) return NULL; 
        if (index < arr->len) return arr->data + index; 
        return fetch(arr->next, index - arr->len); 
    } 
    
    int main(void) { 
        double a1[2] = {1, 2}; 
        double a2[3] = {1, 2, 3}; 
        double a3[1] = {1}; 
        struct dblarr x1, x2, x3; 
    
        x1.data = a1; x1.len = sizeof a1/sizeof *a1; x1.next = &x2; 
        x2.data = a2; x2.len = sizeof a2/sizeof *a2; x2.next = &x3; 
        x3.data = a3; x3.len = sizeof a3/sizeof *a3; x3.next = NULL; 
    
        printf("before %f\n", *fetch(&x1, 5)); 
        *fetch(&x1, 5) = 0.42; 
        printf(" after %f\n", *fetch(&x1, 5)); 
    
        return 0; 
    } 
    

    あなたはhttp://ideone.com/mY0ixで「コードが実行して見る」ことができます。

    +0

    ああ、クールなリンクリスト+再帰的なソリューションです。 –

    +0

    ドライブの1時間後、私は改善が考えられました。 'fetch'関数は、正しい値(またはNULL)へのポインタを返す必要があります。そうすれば、配列に読み書きすることができます。 *回答は編集* – pmg

    0

    配列が連続している必要がない場合は、1つのインデックスを2つのインデックス、つまり実際の配列へのポインタの配列と、目的の要素を持つ配列の配列に変換する方法があります。これを行うには

    、あなたはそれらの配列へのポインタの配列を作成します。

    double** arrays = {a1, a2, a3}; 
    

    その後、それらの長さの配列:

    int arraysizes = { sizeof(a1)/sizeof(*a1), sizeof(a2)/sizeof(*a2), sizeof(a3)/sizeof(*a3) }; 
    

    を次に、あなたが計算することができ、インデックスn、与えられましたすることによっての2つの指標を

    int i1 = 0, j = 0; 
    
    while (n - arraysizes[j] >= 0) 
        n -= arraysizes[j++], ++i1; 
    

    そして、あなたは、このようなポインタの配列インデックスは、実際の要素を取得することができます。

    arrays[n][i2] 
    

    あなたはまた、operator[]が組み込まれて、この計算を行うにはラッパークラスを作成することができます。

    0

    次のような場合はどうですか?かなりハードコーディングされていて、最高の/きれいなコードではありませんが、おそらくあなたはこのロジックを一般化できますか?

    #include <iostream> 
    #include <vector> 
    using namespace std; 
    
    void logicalConcat(vector<int>& a1, vector<int>& a2, vector<int>& a3, int k) { 
    
        if(k > a1.size() - 1) 
         k -= a1.size(); 
        else { 
         cout << a1[k] << endl; 
         return; 
        } 
    
        if(k > a2.size() - 1) 
         k -= a1.size(); 
        else { 
         cout << a2[k] << endl; 
         return; 
        } 
    
        cout << a3[k] << endl; 
    } 
    

    ここで、kは必要なバーチャルコンカチネーションのインデックスになります。ベクトルを繰り返し処理するだけで何も連結しません。ここで

    0

    その他のいくつかは、基本的なC実装の答えを提供します。

    ここでは、配列要素のいずれもコピーせずに仮想連結配列を作成するクラスの汎用C++実装のサンプルコードを示します。作成された仮想配列は、通常のベクトルのように(読み書きするために)インデックスできます。

    #include <vector> 
    #include <map> 
    #include <iostream>; 
    using namespace std; 
    
    class VirtualArray { 
    public: 
        multimap<int,double*> startIndices; // reverse map of starting index to its sub array 
        int size; 
    
        VirtualArray() : size(0) {} 
    
        double & operator[](int i) { 
         // find proper subarray in log(n) time 
         multimap<int,double*>::iterator iter = --startIndices.upper_bound(i); 
         double *subarray = iter->second; 
         int startIndex = iter->first; 
    
         // index into subarray 
         return subarray[i-startIndex]; 
        } 
    
        void addArray(double* array, int length) { 
         startIndices.insert(make_pair(size, array)); 
         size += length; 
        } 
    
        void addVector(vector<double> & vec) { 
         startIndices.insert(make_pair(size, vec.data())); 
         size += vec.size(); 
        } 
    }; 
    
    int main() { 
        double a1[3], a2[4], a3[6] = {1, 2, 3, 4, 5, 6}; 
        int L1 = 3, L2 = 4, L3 = 6; 
    
        vector<double> a3vec; 
        a3vec.assign(a3,a3+6); 
    
        VirtualArray vArray; 
        vArray.addArray(a1,L1); 
        vArray.addArray(a2,L2); 
        vArray.addVector(a3vec); 
    
        cout << vArray[10]; 
        return 0; 
    }