2

基本的に、これらのグローバル変数を使用して割り当て用の OpenCL プログラムをずさんにコーディングしました。

int devType = CL_DEVICE_TYPE_GPU;

cl_int err;         /* Error code returned from api calls.  */
size_t global;      /* Global domain size for our calculation.  */
size_t local;           /* Local domain size for our calculation.  */

cl_platform_id cpPlatform;  /* openCL platform.  */
cl_device_id device_id; /* Compute device id.  */
cl_context context;     /* Compute context.  */
cl_command_queue commands;  /* Compute command queue.  */
cl_program program;     /* Compute program.  */
cl_kernel kernel;       /* Compute kernel.  */

/* Create data for the run.  */
float *data = NULL;     /* Original data set given to device.  */
float *results = NULL;  /* Results returned from device.  */
unsigned int correct;       /* Number of correct results returned.  */
cl_mem input;           /* Device memory used for the input array.  */
cl_mem output;      /* Device memory used for the output SUM.  */

int rc = EXIT_FAILURE;

現在、プログラムを整理するために、それらをすべてローカルにしようとしています。

上記の変数から main() 関数に移動するだけで、グローバル変数 N を変換しました。次に、N を使用するすべての関数ヘッダーを更新して、パラメーターとして 'int N' を持ち、N を引数として必要とするすべての関数呼び出しに N を渡しました。プログラムは期待どおりに機能しました。

ですから、私が求めているのは、これらの変数の残りについては、それほど単純でしょうか? 参照と値による受け渡しの概念を理解しており、一部の関数が変数を変更する可能性があることを理解しているため、ポインター参照/逆参照を使用する必要があります。私の懸念は、私のポインター理論が少し大まかで、問題が発生するのではないかと心配していることです。また、定義した関数がこれらの cl 変数をすべて使用できるかどうかもわかりません。

また、関数内で同じ変数名を使用することに問題はありますか?

編集:

恐れていたとおり、device_id をローカライズしようとすると、次の関数で問題が発生します。

void deviceSetup(int devType) {
    cl_platform_id cpPlatform;  /* openCL platform.  */

    /* Connect to a compute device.  */
    if (CL_SUCCESS != clGetPlatformIDs (1, &cpPlatform, NULL))
        die ("Error: Failed to find a platform!");

    /* Get a device of the appropriate type.  */
    if (CL_SUCCESS != clGetDeviceIDs (cpPlatform, devType, 1, &device_id, NULL))
        die ("Error: Failed to create a device group!");
}

/* Create a compute context.  */
void createContext(cl_int err){
    context = clCreateContext (0, 1, &device_id, NULL, NULL, &err);
    if (!context || err != CL_SUCCESS)
        die ("Error: Failed to create a compute context!");
}

/* Create a command commands.  */
void createCommandQueue(cl_int err) {
    commands = clCreateCommandQueue (context, device_id, 0, &err);
    if (!commands || err != CL_SUCCESS)
        die ("Error: Failed to create a command commands!");
}       

void createAndCompile(cl_int err){
    /* Create the compute program from the source buffer.  */
    program = clCreateProgramWithSource (context, 1,
                                         (const char **) &KernelSource,
                                         NULL, &err);
    if (!program || err != CL_SUCCESS)
        die ("Error: Failed to create compute program!");

    /* Build the program executable.  */
    err = clBuildProgram (program, 0, NULL, NULL, NULL, NULL);
    if (err != CL_SUCCESS)
    {
        size_t len;
        char buffer[2048];

        clGetProgramBuildInfo (program, device_id, CL_PROGRAM_BUILD_LOG,
                               sizeof (buffer), buffer, &len);
        die ("Error: Failed to build program executable!\n%s", buffer);
    }
}
4

1 に答える 1

5

あなたは本当にあなた自身の質問に答えました。はい、本当にそれだけです。関数の大量のパラメーター リストを生成したことがわかった場合は、多数の関連する変数を構造体に結合し、その構造体へのポインターのみを渡すことを検討することをお勧めしますが、それだけです。(任意の関数に渡すパラメーターの数に関連して、パフォーマンスに関するわずかな考慮事項がありますが、今のところ、これは不要な複雑さのレベルであり、なくても済むと思います!)

ただし、C のポインターを理解することから逃れることはできません (参照渡しの唯一の方法です) ので、このような小さなプロジェクトは、その知識を強化するのに理想的な時期かもしれません!

OK、例を挙げましょう。人生は常にそのように説明する方が適切です。

我々は持っています:

int cheddar;
int montereyjack;
int brie;

void print_cheeses(void)
{
    printf("I have %d cheddar %d montereyjack and %d brie\n", cheddar, montereyjack, brie);
}

void add_cheeses(void)
{
   cheddar = cheddar + 1;
   montereyjack = montereyjack + 1;
   brie = brie + 1;
   print_cheeses();
}

int main(int argc, char *argv[])
{
    add_cheeses();
    printf ("Now I have %d cheddars %d jacks %d bries\n", cheddar, montereyjack, brie);
}

到達する必要があるのは次のとおりです。

// By value here because we're not changing anything
void print_cheeses(int cheds, int jacks, int bries)
{
    printf("I have %d cheddar %d montereyjack and %d brie\n", cheds, jacks, bries);
}

// Pointers here because we need to change the values in main
void add_cheeses(int *cheese_one, int *cheese_two, int *cheese_three)
{
   *cheese_one = *cheese_one + 1; // We're following the pointer to get to the data we want to change
   *cheese_two = *cheese_two + 1;
   *cheese_three = *cheese_three + 1;
   print_cheeses(*cheese_one, *cheese_two, *cheese_three); // We're following the pointer to get to the data we want to print
}

int main(int argc, char *argv[])
{
    int cheddar = 0;
    int montereyjack = 0;
    int brie = 0;

    add_cheeses(&cheddar, &montereyjack, &brie);

    printf ("Now I have %d cheddars %d jacks %d bries\n", cheddar, montereyjack, brie);
}

しかし、毎回 3 つの値すべてを渡すのは面倒な場合があります。それらは関連しているため、それらを 1 つの構造体にまとめて、その構造体へのポインターを渡すだけで済みます。

于 2012-11-14T18:10:39.983 に答える