11

OpenCL を取得して、OpenCL 実装が利用可能なすべての一意の物理デバイスのリストを取得する方法はありますか? プラットフォーム/デバイス リストを反復処理する方法は知っていますが、たとえば、私の場合、CPU に効率的なデバイス実装を提供する Intel 提供のプラットフォームと、GPU に高速な実装を提供する APP プラットフォームがありますが、私のCPUにとってはひどい実装です。

2 つの CPU デバイスが実際には同じ物理デバイスであることを確認する方法はありますか?単一の物理デバイス?

私は見ましたが、私の問題は解決CL_DEVICE_VENDOR_IDCL_DEVICE_NAMEませんCL_DEVICE_NAME。同じモデル (デュアル GPU) の 2 つの別々の物理デバイスで同じCL_DEVICE_VENDOR_IDになり、プラットフォームに応じて CPU に異なる ID が与えられます。

理想的な解決策は、ある種の一意の物理デバイス ID ですが、OpenCL 構成を手動で変更して自分でデバイスを再配置できれば幸いです (そのようなことが可能であれば)。

4

4 に答える 4

5

現在この問題を調査できる限り、信頼できる解決策はありません。すべての作業が 1 つのプロセス内で行われる場合は、clGetDeviceIDsまたはcl_device値自体 (本質的にはポインター) によって返されるエントリの順序を使用できますが、それらの識別子をプロセス間で共有しようとすると、事態はさらに悪化します。

その男のブログ投稿を参照してください。

問題は、2 つの同一の GPU がある場合、それらを区別できないことです。を呼び出した場合clGetDeviceIDs、それらが返される順序は実際には指定されていないため、最初のプロセスが最初のデバイスを選択し、2 番目のプロセスが 2 番目のデバイスを取得すると、両方が同じ GPU をオーバーサブスクライブし、もう一方をアイドル状態のままにする可能性があります。

ただし、nVidia と AMD は独自の拡張機能を提供してcl_amd_device_topologyおり、cl_nv_device_attribute_query. これらの拡張機能がデバイスでサポートされているかどうかを確認してから、次のように使用できます (元の作成者によるコード)。

// This cl_ext is provided as part of the AMD APP SDK
#include <CL/cl_ext.h>

cl_device_topology_amd topology;
status = clGetDeviceInfo (devices[i], CL_DEVICE_TOPOLOGY_AMD,
    sizeof(cl_device_topology_amd), &topology, NULL);

if(status != CL_SUCCESS) {
    // Handle error
}

if (topology.raw.type == CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD) {
    std::cout << "INFO: Topology: " << "PCI[ B#" << (int)topology.pcie.bus
        << ", D#" << (int)topology.pcie.device << ", F#"
        << (int)topology.pcie.function << " ]" << std::endl;
}

または(私のコード、上記のリンクされた投稿から改作):

#define CL_DEVICE_PCI_BUS_ID_NV  0x4008
#define CL_DEVICE_PCI_SLOT_ID_NV 0x4009

cl_int bus_id;
cl_int slot_id;

status = clGetDeviceInfo (devices[i], CL_DEVICE_PCI_BUS_ID_NV,
    sizeof(cl_int), &bus_id, NULL);
if (status != CL_SUCCESS) {
    // Handle error.
}

status = clGetDeviceInfo (devices[i], CL_DEVICE_PCI_BUS_ID_NV,
    sizeof(cl_int), &slot_id, NULL);
if (status != CL_SUCCESS) {
    // Handle error.
}

std::cout << "Topology = [" << bus_id <<
                         ":"<< slot_id << "]" << std::endl;
于 2016-03-15T20:06:53.230 に答える
3
  • 1 つのプラットフォームに属しているまったく同じ種類の 2 つのデバイスがある場合、clGetDeviceIDs によって返される関連付けられた cl_device_ids によってそれらを区別できます。

  • 2 つの異なるプラットフォームで使用できるデバイスがある場合は、CL_DEVICE_NAME のデバイス名を比較することで、2 番目のプラットフォームのエントリを削除できます。

  • デバイスの目的のプラットフォームを見つけたい場合は、clGetPlatformInfo() および clGetDeviceInfo からの CL_PLATFORM_VENDOR および CL_DEVICE_VENDOR 文字列をそれぞれ比較します。

すべてのプラットフォームとそれに関連付けられているすべてのデバイスを個別のプラットフォーム固有のリストに読み込み、個別のリスト内のデバイス名を比較して重複を排除できます。これにより、異なるプラットフォームで同じデバイスを取得しないようにする必要があります。

最後に、たとえばコマンド ライン引数または構成ファイルを使用して、アプリケーションに引数を与えて、特定のタイプ (CPU、GPU、アクセラレータ) のデバイスを特定のプラットフォームに関連付けることができます (デバイス タイプに対して異なるプラットフォームの選択肢がある場合)。うまくいけば、これはあなたの質問に答えます。

于 2013-11-07T13:16:27.653 に答える
0

とにかく、すべてのデバイスの一意の ID を取得しようとしていると仮定しましょう。実際には、clGetDeviceIDs を使用して単純にクエリを実行できます。

cl_int clGetDeviceIDs(cl_platform_id platform,
                      cl_device_type device_type,
                      cl_uint num_entries,
                      cl_device_id *devices,
                      cl_uint *num_devices)

次に、デバイスのリストが *devices 配列に挿入され、clGetDeviceInfo() を実行して、使用するデバイスを見つけることができます。

于 2012-06-02T02:27:22.703 に答える
0

上記の回答を組み合わせると、私の解決策は次のとおりです。

long bus = 0; // leave it 0 for Intel
// update bus for NVIDIA/AMD ...
// ...
long uid = (bus << 5) | device_type;

前述のfiregurafikuのように、変数はbusNVIDIA/AMD デバイス固有の情報クエリに従って計算され、 Steininが示唆したように、変数はAPI 呼び出しの結果でした。device_typeclGetDeviceInfo(clDevice, CL_DEVICE_TYPE, sizeof(cl_device_type), &device_type, nullptr)

このようなアプローチにより、GPU が統合された Intel CPU の一意の ID が同じであるという問題が解決されました。異なる のおかげで、両方のデバイスに一意の識別子が割り当てられましたCL_DEVICE_TYPE

驚くべきことに、 Oclgrindでエミュレートされたデバイスでコードを実行する場合、デバイスはシステム上の他のOclgrind simulatorデバイスとは異なる一意の識別子も取得します。15

提案されたアプローチが失敗する可能性がある唯一のケース - 単一のメインボード上の同じモデルの複数の CPU。

于 2019-04-30T18:30:17.517 に答える