WordPress implode & wp_insert_post question

The second parameter to wp_set_object_terms() takes an array, integer, or string.

(array/int/string)
(required) The slug or id of the term (such as category or tag
IDs), will replace all existing related terms in this taxonomy. To
clear or remove all terms from an object, pass an empty string or
NULL. Integers are interpreted as tag IDs. Warning: some
functions may return term_ids as strings which will be interpreted as
slugs consisting of numeric characters!

You create an array ($cardet["marks"]) but then implode() it. When you implode() it you turn that array into a comma separated string, which wp_set_object_terms() interprets as a single value. wp_set_object_terms() will not break the string on commas and create multiple terms for you, but the solution is simple as you’ve added a step that is breaking things. Remove that step and pass the array to wp_set_object_terms().

if ( isset( $cardet['marks'] ) )
    wp_set_object_terms( $post_id, $cardet["marks"], 'mark' );

There is sample code in the Codex doing exactly this, but with IDs:

// An array of IDs of categories we want this post to have.
$cat_ids = array( 6, 8 );

/*
 * If this was coming from the database or another source, we would need to make sure
 * these where integers:

$cat_ids = array_map( 'intval', $cat_ids );
$cat_ids = array_unique( $cat_ids );

 */

$term_taxonomy_ids = wp_set_object_terms( 42, $cat_ids, 'category' );

If $cardet["marks"] is user supplied data please sanitize it before using it.