libmcl-sys 0.1.2-rc1

This system crate provides Rust language bindings to the Minos Compute Library (MCL)
Documentation
#include <getopt.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include "utils.h"
#include <minos.h>

/*
 * Use the pointer to store the actual values, rather than
 * the address at which the value is stored.
 */
int fact_seq_native(uint64_t n, uint64_t *out) {
    uint64_t f = 1;
    uint64_t c;

    for (c = 1; c <= n; c++)
        f = f * c;

    *out = f;

    return 0;
}

/*
 * Use the pointer to store the actual values, rather than
 * the address at which the value is stored.
 */
int fact_seq(void *in, size_t isize, void **out, size_t *osize) {
    uint64_t n = (uint64_t)in;
    uint64_t f = 1;
    uint64_t c;

    for (c = 1; c <= n; c++)
        f = f * c;

    *out = (void *)f;
    *osize = sizeof(uint64_t);

    return 0;
}

int main(int argc, char **argv) {
    uint64_t i;
    mcl_handle **hdls;
    struct timespec start, end;
    uint64_t *in, *out, *out_test;
    int ret = 0;
    uint64_t pes[MCL_DEV_DIMS] = {1, 1, 1};
    unsigned int errs, submitted;
    char src_path[1024];

    strcpy(src_path, XSTR(_MCL_TEST_PATH));
    strcat(src_path, "/exec.cl");

    mcl_banner("EXEC Request Test");

    parse_global_opts(argc, argv);

    hdls = (mcl_handle **)malloc(rep * sizeof(mcl_handle *));
    in = (uint64_t *)malloc(rep * sizeof(uint64_t));
    out = (uint64_t *)malloc(rep * sizeof(uint64_t));
    out_test = (uint64_t *)malloc(rep * sizeof(uint64_t));

    if (!in || !out || !out_test) {
        printf("Error allocating memory. Aborting.\n");
        goto err;
    }

    mcl_init(workers, 0x0);

    // Use the pointer to input to contain data, ensure 0 doesn't come up from rand()
    for (i = 0; i < rep; i++)
        in[i] = (rand() % BASE) + 1;

    printf("Native Test...");
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < rep; i++) {
        fact_seq_native(in[i], &out_test[i]);
    }
    clock_gettime(CLOCK_MONOTONIC, &end);

    printf("Done.\n  Test time: %f seconds\n", ((float)tdiff(end, start)) / BILLION);
#ifdef VERBOSE
    for (i = 0; i < rep; i++)
        printf("  %" PRIu64 " Factorial of %" PRIu64 " = %" PRIu64 "\n", i, in[i],
               out_test[i]);
#endif

    printf("Synchronous Test...");
    clock_gettime(CLOCK_MONOTONIC, &start);
    if (mcl_prg_load(src_path, "", MCL_PRG_SRC)) {
        printf("Error loading program.\n");
        goto err;
    }

    for (i = 0, errs = 0, submitted = 0; i < rep; i++) {
        hdls[i] = mcl_task_create();

        if (!hdls[i]) {
            printf("Error creating task %" PRIu64 ".\n", i);
            goto err;
        }

        if (mcl_task_set_kernel(hdls[i], "FACT", 2)) {
            printf("Error setting task kernel %s for request %" PRIu64 ".\n", "FACT", i);
            goto err;
        }

        if (mcl_task_set_arg(hdls[i], 0, (void *)&(in[i]), sizeof(uint64_t),
                             MCL_ARG_INPUT | MCL_ARG_SCALAR)) {
            printf("Error setting argument for task %" PRIu64 ".\n", i);
            goto err;
        }

        if (mcl_task_set_arg(hdls[i], 1, (void *)&(out[i]), sizeof(uint64_t),
                             MCL_ARG_OUTPUT | MCL_ARG_BUFFER)) {
            printf("Error setting output for task %" PRIu64 ".\n", i);
            goto err;
        }

        if (mcl_exec(hdls[i], pes, NULL, MCL_TASK_ANY)) {
            printf("Error executing task %" PRIu64 ".", i);
            goto err;
        }

        submitted++;

        if (mcl_wait(hdls[i]))
            printf("Request %" PRIu64 " timed out!", i);
    }
    clock_gettime(CLOCK_MONOTONIC, &end);

    for (i = 0; i < rep; i++)
        if (hdls[i]->status != MCL_REQ_COMPLETED || out_test[i] != out[i]) {
            printf("Request %" PRIu64 " ref value=%" PRIu64 " comp value=%" PRIu64
                   " status=%" PRIx64 " retrun=%x" PRIx64 "\n",
                   i, out_test[i], out[i], hdls[i]->status, hdls[i]->ret);
            ret = 1;
            errs++;
        }

    if (!errs)
        printf("Done.\n  Test time: %f seconds\n", ((float)tdiff(end, start)) / BILLION);
    else
        printf("Detected %u errors!\n", errs);

    for (i = 0; i < rep; i++)
        mcl_hdl_free(hdls[i]);

    printf("Asynchronous Test...");
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0, errs = 0, submitted = 0; i < rep; i++) {

        hdls[i] = mcl_task_create();
        if (!hdls[i]) {
            printf("Error creating task%" PRIu64 ".", i);
            goto err;
        }

        if (mcl_task_set_kernel(hdls[i], "FACT", 2)) {
            printf("Error setting task kernel %s for request %" PRIu64 ".\n", "FACT", i);
            goto err;
        }

        if (mcl_task_set_arg(hdls[i], 0, (void *)&(in[i]), sizeof(uint64_t),
                             MCL_ARG_INPUT | MCL_ARG_SCALAR)) {
            printf("Error setting argument for task %" PRIu64 ".\n", i);
            goto err;
        }

        if (mcl_task_set_arg(hdls[i], 1, (void *)&(out[i]), sizeof(uint64_t),
                             MCL_ARG_OUTPUT | MCL_ARG_BUFFER)) {
            printf("Error setting output for task %" PRIu64 ".\n", i);
            goto err;
        }

        if (mcl_exec(hdls[i], pes, NULL, MCL_TASK_ANY)) {
            printf("Error executing task %" PRIu64 ".", i);
            goto err;
        }

        submitted++;
    }

    if (submitted == rep)
        mcl_wait_all();
    else
        printf("Not all requests have been successfully submitted! (%u/%" PRIu64 ")\n", submitted, rep);

    clock_gettime(CLOCK_MONOTONIC, &end);

    for (i = 0; i < rep; i++)
        if (hdls[i]->status != MCL_REQ_COMPLETED || out_test[i] != out[i]) {
            printf("Request %" PRIu64 " ref value=%" PRIu64 " comp value=%" PRIu64
                   " status=%" PRIx64 " retrun=%x" PRIx64 "\n",
                   i, out_test[i], out[i], hdls[i]->status, hdls[i]->ret);
            ret = 1;
            errs++;
        }

    if (!errs)
        printf("Done.\n  Test time: %f seconds\n", ((float)tdiff(end, start)) / BILLION);
    else
        printf("Detected %u errors!\n", errs);

    for (i = 0; i < rep; i++)
        mcl_hdl_free(hdls[i]);

    mcl_finit();
    mcl_verify(ret);

    free(out);
    free(in);
    free(hdls);

    return 0;

err:
    exit(EXIT_FAILURE);
}