与数组的虚级联

时间:2012-02-10 16:31:11

标签: c++ c cuda

假设我有3个双精度数组a1[]a2[]a3[],每个长度为L1,L2,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]

我该怎么做

  • in C
  • 在C ++中(如何使用std :: vectors代替数组) 也很有用)
  • in CUDA

我怀疑是否有办法做到这一点,对于所有这三种环境都是一样的,但是在每个环境中可能有更有效的方法来实现这一点,具体取决于 提供的功能。

4 个答案:

答案 0 :(得分: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处“查看正在运行的代码”。

答案 1 :(得分:0)

如果数组不需要连续,那么一种方法是将单个索引转换为两个索引,一个用于指向实数组的指针数组,另一个用于具有所需元素的数组。< / p>

为此,您将创建一个指向这些数组的指针数组:

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

然后是他们长度的数组:

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

然后,给定索引n,您可以通过

计算arrays的两个索引
int i1 = 0, j = 0;

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

然后您可以像这样索引指针数组以获取实际元素:

arrays[n][i2]

您还可以使用内置的operator[]创建一个包装类来执行此算术。

答案 2 :(得分: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将是您想要的虚级联的索引。我们不会连接任何东西,只是迭代向量。

答案 3 :(得分: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;
}