3

我刚开始使用 C++ AMP(作为学习它的一种方式),但在性能方面我没有得到预期的结果,也许你可以帮助我。

要解决的问题很简单,我有一个向量和一个矩阵结构(C++ 代码,顺便说一句,我是 C++ 的新手)

struct Vector
{
    public : float X, Y, Z;
};

struct Matrix
{
    public : float M11, M12, M13, M14,
                   M21, M22, M23, M24,
                   M31, M32, M33, M34,
                   M41, M42, M43, M44;
};

目标是将同一个矩阵一遍又一遍地乘以数百万个这些向量。下面是进行计算的代码:

Vector compute(const Matrix matrix, const Vector vector) restrict(amp,cpu)
{
    float tx = vector.X;
    float ty = vector.Y;
    float tz = vector.Z;

    Vector result;

    result.X = (matrix.M11 * tx) + (matrix.M12 * ty) + (matrix.M13 * tz) + matrix.M14;
    result.Y = (matrix.M21 * tx) + (matrix.M22 * ty) + (matrix.M23 * tz) + matrix.M24;
    result.Z = (matrix.M31 * tx) + (matrix.M32 * ty) + (matrix.M33 * tz) + matrix.M34;

    return result;
}

现在我可以在 CPU 或 GPU 中调用 run 这个方法。

中央处理器:

Vector* cpu_compute(const Matrix matrix, const Vector *vectors, const int size)
{
    Vector *result = (Vector*)malloc(size * sizeof(Vector));

    for (int i = 0; i < size; ++i)
    {
        result[i] = compute(matrix, vectors[i]);
    }

    return result;
}

显卡:

Vector* gpu_compute(const Matrix matrix, const Vector *vectors, const int size)
{
    Vector *result = (Vector*)malloc(size * sizeof(Vector));

    array_view<const Vector, 1> vectors_view(size, vectors);
    array_view<Vector, 1> result_view(size, result);

    accelerator acc = pick_accelerator();

    parallel_for_each(acc.default_view, vectors_view.extent, [=](index<1> idx) restrict(amp)
    {
        result_view[idx] = compute(matrix, vectors_view[idx]);
    });

    return result;
}

使用 2020 万个向量运行此代码时,我得到以下结果:

  • CPU (C++): 226ms
  • CPU (C#) : 223 毫秒
  • 显卡:339 毫秒

我有几个惊喜。首先,C# 和 C++ 代码以几乎相同的速度运行。其次,GPU 没有我希望的那么快。

我知道你必须为内存传输付出代价,但我认为这个例子不会那么明显。无论我输入多少数据,GPU总是较慢。那就是说我做错了什么,否则如果被单核cpu打败,没人会用GPU玩游戏。

问题:有没有一种方法可以在 GPU 上比在 CPU 上进行这种计算?

谢谢

仅供参考:我正在运行 Windows 7(这使我无法使用 WARP),配备 NVIDIA GeForce GTX 690 和 Intel Core i7 3930k。

4

2 回答 2

3

现在,您正在支付将结果数据复制到 GPU 上的开销,即使您只写过它。

array_view<Vector, 1> result_view(size, result);
result_view.discard_data()

您应该调用 discard_data() 以便不复制此数据。

即使考虑到这一点,您也不太可能在这里看到显着的加速,因为您所做的工作量不会隐藏与 GPU 之间的副本成本。

另一个旁注。您可以尝试将您的 C++ 版本编写为循环,并查看是否可以让编译器自动矢量化计算。这是微不足道的,可能会给你一个显着的加速。

自动并行化和自动矢量化

于 2013-09-07T17:58:21.233 回答
2

可能您的内存访问计算比率很差。

内存访问很昂贵(从 CPU 复制到 GPU 并返回),而在复制的内存上的计算会很便宜(强大的 GPU)。

您只需进行少量计算并经常访问新值。

为了验证这种情况,您可以注释掉计算并查看运行时间(仅用于复制)是多少。

此外,如果您刚开始,请在 codeplex 上获取 amp 书籍示例,您还可以很好地了解哪些工作方式。

于 2013-07-03T22:11:36.447 回答