|
@@ -30,7 +30,6 @@
|
|
|
|
|
|
#include "sink_common.h"
|
|
|
|
|
|
-
|
|
|
/* Return the sink kind of the running process, based on the value of the
|
|
|
* STARPU_SINK environment variable.
|
|
|
* If there is no valid value retrieved, return STARPU_INVALID_KIND
|
|
@@ -108,51 +107,156 @@ void _starpu_sink_common_free(const struct _starpu_mp_node *mp_node STARPU_ATTRI
|
|
|
free(*(void **)(arg));
|
|
|
}
|
|
|
|
|
|
-static void _starpu_sink_common_copy_from_host(const struct _starpu_mp_node *mp_node,
|
|
|
+static void _starpu_sink_common_copy_from_host_sync(const struct _starpu_mp_node *mp_node,
|
|
|
void *arg, int arg_size)
|
|
|
{
|
|
|
STARPU_ASSERT(arg_size == sizeof(struct _starpu_mp_transfer_command));
|
|
|
|
|
|
- struct _starpu_mp_transfer_command *cmd = (struct _starpu_mp_transfer_command *)arg;
|
|
|
+ struct _starpu_mp_transfer_command *cmd = (struct _starpu_mp_transfer_command *)arg;
|
|
|
|
|
|
- mp_node->dt_recv(mp_node, cmd->addr, cmd->size);
|
|
|
+ mp_node->dt_recv(mp_node, cmd->addr, cmd->size, NULL);
|
|
|
}
|
|
|
|
|
|
-static void _starpu_sink_common_copy_to_host(const struct _starpu_mp_node *mp_node,
|
|
|
+
|
|
|
+static void _starpu_sink_common_copy_from_host_async(struct _starpu_mp_node *mp_node,
|
|
|
+ void *arg, int arg_size)
|
|
|
+{
|
|
|
+ STARPU_ASSERT(arg_size == sizeof(struct _starpu_mp_transfer_command));
|
|
|
+
|
|
|
+ struct _starpu_mp_transfer_command *cmd = (struct _starpu_mp_transfer_command *)arg;
|
|
|
+
|
|
|
+ /* For asynchronous transfers, we store events to test them later when they are finished */
|
|
|
+ struct _starpu_mp_event * sink_event = _starpu_mp_event_new();
|
|
|
+ /* Save the command to send */
|
|
|
+ sink_event->answer_cmd = STARPU_RECV_FROM_HOST_ASYNC_COMPLETED;
|
|
|
+ sink_event->remote_event = cmd->event;
|
|
|
+
|
|
|
+ /* Set the sender (host) ready because we don't want to wait its ack */
|
|
|
+ struct _starpu_async_channel * async_channel = &sink_event->event;
|
|
|
+ async_channel->starpu_mp_common_finished_sender = 1;
|
|
|
+ async_channel->starpu_mp_common_finished_receiver = 0;
|
|
|
+
|
|
|
+ mp_node->dt_recv(mp_node, cmd->addr, cmd->size, &sink_event->event);
|
|
|
+ /* Push event on the list */
|
|
|
+ _starpu_mp_event_list_push_back(&mp_node->event_list, sink_event);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void _starpu_sink_common_copy_to_host_sync(const struct _starpu_mp_node *mp_node,
|
|
|
void *arg, int arg_size)
|
|
|
{
|
|
|
STARPU_ASSERT(arg_size == sizeof(struct _starpu_mp_transfer_command));
|
|
|
|
|
|
struct _starpu_mp_transfer_command *cmd = (struct _starpu_mp_transfer_command *)arg;
|
|
|
+
|
|
|
/* Save values before sending command to prevent the overwriting */
|
|
|
size_t size = cmd->size;
|
|
|
void * addr = cmd->addr;
|
|
|
|
|
|
- _starpu_mp_common_send_command(mp_node, STARPU_SEND_TO_HOST, NULL, 0);
|
|
|
+ _starpu_mp_common_send_command(mp_node, STARPU_SEND_TO_HOST, NULL, 0);
|
|
|
+
|
|
|
+ mp_node->dt_send(mp_node, addr, size, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void _starpu_sink_common_copy_to_host_async(struct _starpu_mp_node *mp_node,
|
|
|
+ void *arg, int arg_size)
|
|
|
+{
|
|
|
+ STARPU_ASSERT(arg_size == sizeof(struct _starpu_mp_transfer_command));
|
|
|
+
|
|
|
+ struct _starpu_mp_transfer_command *cmd = (struct _starpu_mp_transfer_command *)arg;
|
|
|
+
|
|
|
+ /* For asynchronous transfers, we need to say dt_send that we are in async mode
|
|
|
+ * but we don't push event on list because we don't need to know if it's finished
|
|
|
+ */
|
|
|
+ struct _starpu_mp_event * sink_event = _starpu_mp_event_new();
|
|
|
+ /* Save the command to send */
|
|
|
+ sink_event->answer_cmd = STARPU_SEND_TO_HOST_ASYNC_COMPLETED;
|
|
|
+ sink_event->remote_event = cmd->event;
|
|
|
|
|
|
- mp_node->dt_send(mp_node, addr, size);
|
|
|
+ /* Set the receiver (host) ready because we don't want to wait its ack */
|
|
|
+ struct _starpu_async_channel * async_channel = &sink_event->event;
|
|
|
+ async_channel->starpu_mp_common_finished_sender = 0;
|
|
|
+ async_channel->starpu_mp_common_finished_receiver = 1;
|
|
|
+
|
|
|
+ mp_node->dt_send(mp_node, cmd->addr, cmd->size, &sink_event->event);
|
|
|
+ /* Push event on the list */
|
|
|
+ _starpu_mp_event_list_push_back(&mp_node->event_list, sink_event);
|
|
|
}
|
|
|
|
|
|
-static void _starpu_sink_common_copy_from_sink(const struct _starpu_mp_node *mp_node,
|
|
|
+
|
|
|
+static void _starpu_sink_common_copy_from_sink_sync(const struct _starpu_mp_node *mp_node,
|
|
|
void *arg, int arg_size)
|
|
|
{
|
|
|
STARPU_ASSERT(arg_size == sizeof(struct _starpu_mp_transfer_command_to_device));
|
|
|
|
|
|
struct _starpu_mp_transfer_command_to_device *cmd = (struct _starpu_mp_transfer_command_to_device *)arg;
|
|
|
|
|
|
- mp_node->dt_recv_from_device(mp_node, cmd->devid, cmd->addr, cmd->size);
|
|
|
+ mp_node->dt_recv_from_device(mp_node, cmd->devid, cmd->addr, cmd->size, NULL);
|
|
|
+ _starpu_mp_common_send_command(mp_node, STARPU_TRANSFER_COMPLETE, NULL, 0);
|
|
|
+}
|
|
|
|
|
|
- _starpu_mp_common_send_command(mp_node, STARPU_TRANSFER_COMPLETE, NULL, 0);
|
|
|
+
|
|
|
+static void _starpu_sink_common_copy_from_sink_async(struct _starpu_mp_node *mp_node,
|
|
|
+ void *arg, int arg_size)
|
|
|
+{
|
|
|
+ STARPU_ASSERT(arg_size == sizeof(struct _starpu_mp_transfer_command_to_device));
|
|
|
+
|
|
|
+ struct _starpu_mp_transfer_command_to_device *cmd = (struct _starpu_mp_transfer_command_to_device *)arg;
|
|
|
+
|
|
|
+ /* For asynchronous transfers, we store events to test them later when they are finished
|
|
|
+ */
|
|
|
+ struct _starpu_mp_event * sink_event = _starpu_mp_event_new();
|
|
|
+ /* Save the command to send */
|
|
|
+ sink_event->answer_cmd = STARPU_RECV_FROM_SINK_ASYNC_COMPLETED;
|
|
|
+ sink_event->remote_event = cmd->event;
|
|
|
+
|
|
|
+ /* Set the sender ready because we don't want to wait its ack */
|
|
|
+ struct _starpu_async_channel * async_channel = &sink_event->event;
|
|
|
+ async_channel->starpu_mp_common_finished_sender = 1;
|
|
|
+ async_channel->starpu_mp_common_finished_receiver = 0;
|
|
|
+
|
|
|
+ mp_node->dt_recv_from_device(mp_node, cmd->devid, cmd->addr, cmd->size, &sink_event->event);
|
|
|
+ /* Push event on the list */
|
|
|
+ _starpu_mp_event_list_push_back(&mp_node->event_list, sink_event);
|
|
|
}
|
|
|
|
|
|
-static void _starpu_sink_common_copy_to_sink(const struct _starpu_mp_node *mp_node,
|
|
|
+
|
|
|
+static void _starpu_sink_common_copy_to_sink_sync(const struct _starpu_mp_node *mp_node,
|
|
|
void *arg, int arg_size)
|
|
|
{
|
|
|
STARPU_ASSERT(arg_size == sizeof(struct _starpu_mp_transfer_command_to_device));
|
|
|
|
|
|
struct _starpu_mp_transfer_command_to_device *cmd = (struct _starpu_mp_transfer_command_to_device *)arg;
|
|
|
|
|
|
- mp_node->dt_send_to_device(mp_node, cmd->devid, cmd->addr, cmd->size);
|
|
|
+ mp_node->dt_send_to_device(mp_node, cmd->devid, cmd->addr, cmd->size, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void _starpu_sink_common_copy_to_sink_async(struct _starpu_mp_node *mp_node,
|
|
|
+ void *arg, int arg_size)
|
|
|
+{
|
|
|
+ STARPU_ASSERT(arg_size == sizeof(struct _starpu_mp_transfer_command_to_device));
|
|
|
+
|
|
|
+ struct _starpu_mp_transfer_command_to_device *cmd = (struct _starpu_mp_transfer_command_to_device *)arg;
|
|
|
+
|
|
|
+ /* For asynchronous transfers, we need to say dt_send that we are in async mode
|
|
|
+ * but we don't push event on list because we don't need to know if it's finished
|
|
|
+ */
|
|
|
+ struct _starpu_mp_event * sink_event = _starpu_mp_event_new();
|
|
|
+ /* Save the command to send */
|
|
|
+ sink_event->answer_cmd = STARPU_SEND_TO_SINK_ASYNC_COMPLETED;
|
|
|
+ sink_event->remote_event = cmd->event;
|
|
|
+
|
|
|
+ /* Set the receiver ready because we don't want to wait its ack */
|
|
|
+ struct _starpu_async_channel * async_channel = &sink_event->event;
|
|
|
+ async_channel->starpu_mp_common_finished_sender = 0;
|
|
|
+ async_channel->starpu_mp_common_finished_receiver = 1;
|
|
|
+
|
|
|
+ mp_node->dt_send_to_device(mp_node, cmd->devid, cmd->addr, cmd->size, &sink_event->event);
|
|
|
+
|
|
|
+ /* Push event on the list */
|
|
|
+ _starpu_mp_event_list_push_back(&mp_node->event_list, sink_event);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -183,7 +287,7 @@ static void _starpu_sink_common_recv_workers(struct _starpu_mp_node * node, void
|
|
|
|
|
|
/* Retrieve workers */
|
|
|
struct _starpu_worker * workers = &config->workers[baseworkerid];
|
|
|
- node->dt_recv(node,workers,worker_size);
|
|
|
+ node->dt_recv(node,workers,worker_size, NULL);
|
|
|
|
|
|
/* Update workers to have coherent field */
|
|
|
for(i=0; i<nworkers; i++)
|
|
@@ -210,7 +314,7 @@ static void _starpu_sink_common_recv_workers(struct _starpu_mp_node * node, void
|
|
|
|
|
|
/* Retrieve combined workers */
|
|
|
struct _starpu_combined_worker * combined_workers = config->combined_workers;
|
|
|
- node->dt_recv(node, combined_workers, combined_worker_size);
|
|
|
+ node->dt_recv(node, combined_workers, combined_worker_size, NULL);
|
|
|
|
|
|
node->baseworkerid = baseworkerid;
|
|
|
STARPU_PTHREAD_BARRIER_WAIT(&node->init_completed_barrier);
|
|
@@ -272,19 +376,35 @@ void _starpu_sink_common_worker(void)
|
|
|
break;
|
|
|
|
|
|
case STARPU_RECV_FROM_HOST:
|
|
|
- _starpu_sink_common_copy_from_host(node, arg, arg_size);
|
|
|
+ _starpu_sink_common_copy_from_host_sync(node, arg, arg_size);
|
|
|
break;
|
|
|
|
|
|
case STARPU_SEND_TO_HOST:
|
|
|
- _starpu_sink_common_copy_to_host(node, arg, arg_size);
|
|
|
+ _starpu_sink_common_copy_to_host_sync(node, arg, arg_size);
|
|
|
break;
|
|
|
|
|
|
case STARPU_RECV_FROM_SINK:
|
|
|
- _starpu_sink_common_copy_from_sink(node, arg, arg_size);
|
|
|
+ _starpu_sink_common_copy_from_sink_sync(node, arg, arg_size);
|
|
|
break;
|
|
|
|
|
|
case STARPU_SEND_TO_SINK:
|
|
|
- _starpu_sink_common_copy_to_sink(node, arg, arg_size);
|
|
|
+ _starpu_sink_common_copy_to_sink_sync(node, arg, arg_size);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case STARPU_RECV_FROM_HOST_ASYNC:
|
|
|
+ _starpu_sink_common_copy_from_host_async(node, arg, arg_size);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case STARPU_SEND_TO_HOST_ASYNC:
|
|
|
+ _starpu_sink_common_copy_to_host_async(node, arg, arg_size);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case STARPU_RECV_FROM_SINK_ASYNC:
|
|
|
+ _starpu_sink_common_copy_from_sink_async(node, arg, arg_size);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case STARPU_SEND_TO_SINK_ASYNC:
|
|
|
+ _starpu_sink_common_copy_to_sink_async(node, arg, arg_size);
|
|
|
break;
|
|
|
|
|
|
case STARPU_SYNC_WORKERS:
|
|
@@ -312,6 +432,25 @@ void _starpu_sink_common_worker(void)
|
|
|
{
|
|
|
STARPU_PTHREAD_MUTEX_UNLOCK(&node->message_queue_mutex);
|
|
|
}
|
|
|
+
|
|
|
+ //XXX: Need mutex here ?
|
|
|
+ if(!_starpu_mp_event_list_empty(&node->event_list))
|
|
|
+ {
|
|
|
+ struct _starpu_mp_event * sink_event = _starpu_mp_event_list_pop_front(&node->event_list);
|
|
|
+ if (node->dt_test(&sink_event->event))
|
|
|
+ {
|
|
|
+ /* send ACK to host */
|
|
|
+ _starpu_mp_common_send_command(node, sink_event->answer_cmd , &sink_event->remote_event, sizeof(sink_event->remote_event));
|
|
|
+ _starpu_mp_event_delete(sink_event);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ /* try later */
|
|
|
+ _starpu_mp_event_list_push_back(&node->event_list, sink_event);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
STARPU_PTHREAD_KEY_DELETE(worker_key);
|